Return to Phobos

← Zurück zum Forum

Wo stehe ich gerade? Die Steuerung des Raumschiffs ist fertig und ich habe am Wochenende den ersten Missile als "Schuss" fertig gestellt. Jetzt kommt Schuss 2 - also wie bei Phobos soll das Raumschiff abwechselnd links und rechts schiessen können. Das werde ich nächste Woche implementieren und dann den Code hier hochladen. Das ist gar nicht so unkompliziert zu programmieren und ich habe beschlossen, daß ich auf die erweiterten Möglichkeiten vom MADS Crossassembler zurückgreife und if - Bedingungen in den Code mit einbeziehe. Das macht den Code lesbarer und auch einfacher für mich zu programmieren... Die Compabilität zu den alten Assemblern nimmt natürlich ab... ich hoffe ihr könnt auch zukünftig den Code nachvollziehen! Wer aktuell in Assembler programmieren will sollte tatsächlich auf die Umgebung Eclipse mit WUDSN und MADS-Assembler zurückgreifen! LG Peter

AntwortZitat

Sooooo .... ich habe heute die Schüsse des Raumschiffes drin! Dabei habe ich mir ganz schön die Programmierfinger verbogen, denn zwei Missiles so zu programmieren, das sie abwechselnd aus dem rechten bzw. linken "Schussrohr" des Raumschiffes loslaufen und je nach Schusslänge auch durchaus gleichzeitig zu sehen sind ... also zur richtigen Zeit jeweils sperren und freigeben etc. war ganz schön tricky... aber es läuft jetzt. Der Code dafür sieht recht umständlich aus und ich habe mehrere Hilfsvariablen benutzen müssen - es läuft auch noch nicht komplett fehlerfrei - je nach Höhe des Raumschiffes mehr oder weniger gut! Hier muss ich noch ein wenig den Code verfeinern...

Hier der Code für den Header:

var1 = $a0
var2 = $a2
var3 = $a4
var4 = $a6
var5 = $a8
var6 = $b2
var7 = $b4
lms1 = $b6
lms2 = $b8
lmslo = $a0
lmshi = $a2
delay = $b0

play1 = $92
play2 = $94
play3 = $96
play4 = $98

miss1 = $c0
miss2 = $c2
miss3 = $c4
miss4 = $c6
rechts = $c8
links = $c9
xposp1 = $ca
yposp1 = $cb
joyst1 = $cc
kollp0 = $cd

xposm1 = $ce
yposm1 = $cf
xposm2 = $d0
yposm2 = $d1
kollm1 = $d2
kollm2 = $d3

feuer1 = $d4
feuer2 = $d5
yposm1hilf = $d6
feuer3 = $d7
feuer4 = $d8
yposm2hilf = $d9
feuer5 = $da

Und hier der Programmcode:





      org $2000

      icl '../hardware.txt'
      icl '../header.txt'
      icl 'character.asm'
      icl 'lands.asm' 

dlist       .byte 112,112,112,100
      .byte 30,75
      .byte 36,36,36,36,36,36,36,36,36,36,36,36
      .byte 36,36,36,36,36,36,36,36,36,4,112
      .byte 65,32,156

pm1     .byte 0,24,60,36,36,126,126,255,219,219,129,129,129,0

mi1     .byte 15,15,15,15
mi2     .byte 12,12,12,12
mi3     .byte 12,12,12,12

mi4     .byte 12,12,12,12



      .proc main

main1   jsr displaylist ;Subroutine Displaylist-Aufbau
      mva #33 yposp1
      mva #120 xposp1
      mva #42 yposm1
      mva #0 xposm1
      mva #94 yposm2
      mva #100 xposm2

Start1    mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
      mva #192 gprior ;GTIA Modus 3 (16 Farben) initialisieren
      mva #0 color4 ;Hintergrundfarbe / Helligkeit festlegen    
      lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1
      mva <lands var6
      mva >lands var6+1
      mva #0 kollp0

      ; Player vorbereiten und initialisieren

      lda ramtop
      sec
      sbc #16
      sta pmbase
      clc
      adc #3
      sta miss1+1
      adc #1
      sta play1+1

      mva #62 sdmctl
      mva #220 pcolr0
      mva #220 pcolr1
      mva #122 pcolr2
      mva #122 pcolr3
      mva #1 gprior
      mva #3 gractl
      mva #1 sizep0
      mva #1 sizep1
      mva #0 sizem
      mva #0 rechts
      mva #2 hitclr



main2   
      ldy #255        ;Speicher Player 1 leeren
      lda #0
      sta play1
@     sta (play1),y
      dey
      bpl @-
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-

      clc
      ldy #0
      ldx #0
@     lda mi1,x
      sta (miss1),y
      iny
      inx
      cpx #2
      bne @-
      lda xposm1
      sta p0pf
      lda xposm2
      sta p1pf
      ldx #>vbinter     ;VB-Interrupt VektorHi
      ldy #<vbinter     ;VB-Interrupt VektorLo
      lda #7          ;Deferred Mode mit lda #7 festlegen
      jsr setvbv        ;Vektor für die eigene Routine über setvbv eintragen



hauptprogramm

      clc
      lda kollp0
      cmp #1
      bcc @+
      jsr kollision
      jmp start1
@     

      jsr letztereihe     ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)  
      jsr feinscroll      ;Feinscroll Bildschirm1 ausführen (sichtbar)

      mva #$30 var1     ;var1 auf 30000 ($7530) setzen
      mva #$75 var1+1
      mva #$f0 var2     ;var2 auf 30960 ($78f0) setzen
      mva #$78 var2+1

      jsr grobscroll      ;Bildschirm1 kopieren + grobscroll

      mva #$18 var1     ;var1 + var2 auf 31000 ($7918) setzen
      mva #$18 var2
      mva #$79 var1+1
      mva #$79 var2+1 

      mva #1 delay
      jsr wartes

      jsr umschalten      ;umschalten auf Bildschirm2 - Bildschirm2 wird sichtbar 
      jsr letztereihe
      jsr feinscroll      ;Feinscroll Bildschirm2 ausführen (sichtbar)            

      mva #$08 var2     ;var1 auf 29960 ($7508) setzen
      mva #$75 var2+1
      mva #$18 var1     ;var2 auf 31000 ($7918) setzen
      mva #$79 var1+1

      jsr grobscroll      ;;Bildschirm2 kopieren + grobscroll

      mva #$30 var1     ;var1 + var2 auf 30000 ($7530) setzen
      mva #$30 var2
      mva #$75 var1+1
      mva #$75 var2+1

      mva #1 delay
      jsr wartes
      jsr umschalten      ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar


      ;Ende der Bildschirmausführung / Kontrolle Durchläufe

      sec
      lda #38         ; - 36 = Anzahl der Durchläufe
      sbc var6+1
      bpl @+

      jmp start1            ;Stop hier

@     jmp hauptprogramm       ;weiter

      .endp

      ; _____________________________________________________________________________________
      ;
      ; ---------------------------- S U B R O U T I N E N ----------------------------------
      ; _____________________________________________________________________________________




                ;vertical blank interrupt für Joystick / PM

vbinter     
      pha
      txa
      pha
      clc         ;Kollision Player 0 Abfragen
      lda p0pf
      cmp #1
      bcc @+
      mva #1 kollp0
@     mva #2 hitclr

      clc         ;Joystickabfragen Player1
      lda stick0
      cmp #15       ;keine Joystickaktion
      bcs @+
      cmp #14
      bcs nachob
      cmp #13
      bcs nachun
      cmp #11
      bcs nachli
      cmp #10
      bcs nachliob
      cmp #9
      bcs nachliun
      sec
      cmp #7
      bcs nachre
      cmp #6
      bcs nachreob
      cmp #5
      bcs nachreun
@     jmp write

nachre    clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp write

nachreun
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachun

nachreob
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachob

nachli    sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp write

nachliun
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachun

nachliob
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachob

nachob
      dec yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-


      jmp write

nachun

      inc yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-

      jmp write

@     clc
write   
      lda xposp1 
      sta hposp0
      ;---------- Abfrage Feuerknopf und Routine Schuss links-------
      #if .byte strig0<#1 .and .byte feuer3=#0
      #if .byte feuer5=#0 .or .byte feuer5>#180
      mva #1 feuer1
      mva #1 feuer3
      mva xposp1 p0pf
      lda yposp1
      adc #9
      sta feuer2
      #end
      #end
      #if .byte feuer1=#1   
      ldy feuer2
      lda #0
      sta (miss1),y
      iny
      sty feuer2
      iny
      lda #3
      sta (miss1),Y
      #if .byte feuer2=#210
      mva #0 feuer1
      mva #0 feuer2
      lda #0
      dey
      sta (miss1),y
      iny
      sta (miss1),y
      #end
      #end
      ;-------------------------------------------------------------

      ;---------- Abfrage Feuerknopf und Routine Schuss links-------    
      #if .byte strig0<#1 .and feuer3=#1
      #if .byte feuer2=#0 .or .byte feuer2>#180
      mva #1 feuer4
      mva #0 feuer3
      lda xposp1 
      adc #13
      sta p1pf
      lda yposp1
      adc #9
      sta feuer5
      #end
      #end
      #if .byte feuer4=#1   
      ldy feuer5
      lda #0
      sta (miss1),y
      iny
      sty feuer5
      iny
      lda #12
      sta (miss1),Y
      #if .byte feuer5=#210
      mva #0 feuer4
      mva #0 feuer5
      lda #0
      dey
      sta (miss1),y
      iny
      sta (miss1),y
      #end
      #end
      ;-------------------------------------------------------------
@     
      pla
      tax
      pla
      jmp xitvbv      ;vb-interrupt wird über xitvbv beendet!!



      ; -------------------------------------------------------------------------------------

kollision

      lda #22
      sta delay
      jsr wartes
      rts





      ; -------------------------------------------------------------------------------------


umschalten
      ldy #4        ;Bildschirme umschalten von unsichtbar auf sichtbar 
      mva sdlstl var5
      mva sdlstl+1 var5+1
      lda var1
      sta (var5),y
      iny
      lda var1+1
      sta (var5),y
      rts

      ; -------------------------------------------------------------------------------------

wartes    
      clc
        ldx delay ; Warteschleife
st      lda RTCLOK+2    
wa      cmp RTCLOK+2    
          beq wa    
          dex            
          bpl st 
          rts

          ; -------------------------------------------------------------------------------------

feinscroll
      ldy #1
      mva #0 delay
@     jsr wartes
      sty vscrol
      iny
      cpy #8
      bne @-      
      rts

          ; --------------------------------------------------------------------------------------

grobscroll  
      ;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile

      ldx #22
@     ldy #$28
      clc
@     mva (var1),y (var2),y
      dey
      bpl @-
      clc
      lda var1
      adc #$28
      sta var1
      bcc @+
      inc var1+1
@     clc
      lda var2
      adc #$28
      sta var2
      bcc @+
      inc var2+1      
@     clc
      dex
      bpl @-3
      rts

      ; -------------------------------------------------------------------------------

displaylist
      ; initialisiere die Displaylist
      mva sdlstl var5
      mva sdlstl+1 var5+1
      ldy #0
      clc
@     lda dlist,y
      sta (var5),y
      iny
      cpy #34
      bne @-
      rts

      ; ---------------------------------------------------------------------------------------

letztereihe
      ;Die letzte Reihe printen 
      ;Start der letzten Reihe bei var1 - Line 22
      lda var1
      adc #112
      sta var1
      inc var1+1
      inc var1+1
      inc var1+1
      ldy #0
      clc



      lda (var6),y ;Boarder1 holen
      sta var5  ;Boarderanzahl in var5 speichern
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1      
      lda (var6),y
      ldy var5



@     sta (var1),y ;Boarder1 printen
      dey
      bpl @-      
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1  

      lda (var6),y ;Rand Boarder1 holen
      inc var5  ;Zeilenzähler eins weiter
      ldy var5
      sta (var1),y ;Rand Boarder1 printen
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1  

      lda(var6),y ;leer holen
      tax
      lda #0
      ldy var5      
@     iny      
      sta (var1),y ; leer printen
      dex
      bpl @-



      sty var5 ;Zeilenzähler sichern
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1  

      lda(var6),y ;Rand Boarder2 holen
      ldy var5
      iny
      sty var5
      sta (var1),y ;Rand Boarder2 printen
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1  



      lda(var6),y ;Boarder2 holen
      tax   ;Boarderanzahl in x speichern
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1  
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder2 printen
      dex
      bpl @-
      clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1
      mva #0 vscrol
      rts

      ; ------------------------------------------------------------------------------


      run main

zu zu implementierende Landschaft (lands.asm) und Die Charaktertabelle (character.asm) sind noch unverändert!

Wenn erwünscht (für die, die nicht mit Eclipse arbeiten) kann ich auch eine kurze mov -Datei hochstellen ....

Gruß Peter

AntwortZitat

Hallo!

Sind diese "Grafikfehler" bei Dir auch, oder habe ich den Programmcode falsch übernommen?

Phobo1.png

Grüße

Anhänge:

Mein 600XL ist virenfrei!

AntwortZitat

nimm mal für lands.asm diesen Code:

;@com.wudsn.ide.asm.mainsourcefile=test1.asm


lands   .byte 8,2,8,19,10,9,2
      .byte 9,2,8,18,10,12,2
      .byte 9,2,8,17,10,13,2
      .byte 9,2,8,16,10,14,2
      .byte 9,2,8,15,10,16,2
      .byte 9,2,8,14,10,17,2
      .byte 9,2,8,13,10,17,2
      .byte 10,2,8,12,10,17,2
      .byte 11,2,8,11,10,18,2
      .byte 12,2,8,10,10,17,2
      .byte 13,2,8,10,10,15,2
      .byte 14,2,8,10,10,14,2
      .byte 14,2,8,10,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 8,2,8,19,6,8,2
      .byte 9,2,8,18,10,11,2
      .byte 9,2,8,17,10,12,2
      .byte 9,2,8,16,10,13,2
      .byte 9,2,8,15,10,15,2
      .byte 9,2,8,14,10,16,2
      .byte 9,2,8,13,10,17,2
      .byte 10,2,8,12,10,17,2
      .byte 11,2,8,11,10,18,2
      .byte 12,2,8,10,10,17,2
      .byte 13,2,8,10,10,15,2
      .byte 14,2,8,10,10,14,2
      .byte 14,2,8,10,10,14,2 ;34

      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 12,2,8,10,10,17,2
      .byte 13,2,8,10,10,15,2
      .byte 14,2,8,10,10,14,2
      .byte 14,2,8,10,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 11,2,8,12,10,15,2
      .byte 11,2,8,12,10,15,2
      .byte 13,2,8,11,10,14,2
      .byte 13,2,8,11,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 12,2,8,12,10,14,2
      .byte 12,2,8,12,10,14,2 ;68

du hast wohl noch den älteren Code für lands.asm ... bislang habe ich nur eine Testlandschaft drin, die sich dann wiederholt. Daran werde ich jetzt aber relativ zeitnah dran arbeiten. Vorher muss ich aber noch etwas am Player arbeiten und die Kollisionen müssen noch rein!

AntwortZitat

... da meine Frau bis Donnerstag auf Achse ist und ich heute erst ab 15 Uhr zu arbeiten anfange, habe ich ein wenig Zeit zu programmieren...

Den Antrieb vom Raumschiff habe ich etwas angepasst und dabei festgestellt, dass der VBI so langsam ausgereizt ist. Daher habe ich jetzt noch schnell die Kollisionsabfragen für das Raumschiff und die beiden Schüsse in den VBI programmiert. Die beiden Schüsse laufen wie gewohnt nach ganz unten durch wenn keine Barriere im Weg ist, treffen die Schüsse auf die Landschaft, verschwinden sie einfach. Wenn bestimmte Ziele getroffen werden, passiert eine bestimmte Aktion.... das folgt dann bald! Ich habe jetzt einen Player für das Raumschiff und einen für den Antrieb benutzt, zwei Missile für die beiden Schüsse und zwei Missile fürs Blinken. Das läuft jetzt recht stabil, ab und zu passiert mal ein kleiner Grafikfehler, den ich noch nicht entdeckt habe. Später..... Ich bin mir aber noch nicht so ganz sicher, ob ich das nochmal umprogrammieren muss... vielleicht baue ich später das Blinken um und nutze dafür einen Player - die beiden gesparten Missile nutze ich dann für 4 statt 2 Schüsse. Auch mit dem Aufbau der Schüsse bin ich nicht so ganz zufrieden, das muss ich nochmal grundsätzlich umprogrammieren, damit alles etwas schlanker und besser läuft... Aber so wie es jetzt ist, funktioniert schon alles recht gut und ich baue jetzt erstmal die Landschaft aus. Auch hier muss ich etwas umprogrammieren, denn der Aufbau der letzten Reihe (hier wird ja die Landschaft kontinuierlich aus den Datensätzen gebildet) beinhaltet noch nicht die Items, die das Raumschiff abschießen soll/muss. Das gehe ich jetzt als nächstes an! Gruß Peter

AntwortZitat

... die Character habe ich angepasst - ein erstes "Item" ist fertig, nämlich der FUEL-Tank ... die Landschaft habe ich etwas erweitert: Statt 7 Bytes sind jetzt 9 Bytes pro Reihe hinterlegt, die letzten beiden Bytes legen in einer Reihe fest, welches Item an welcher Position geprintet wird - drei Tanks habe ich bereits integriert in die Landschaft, die ich entsprechend auch vergrößert habe... ... die letzte Reihe habe ich entsprechend angepasst, die Items werden jetzt erkannt (sofern in der Landschaft hinterlegt) und geprintet... Gruß und ein schönes WEBildschirmfoto 2021-11-19 um 19.42.18.png

Anhänge:
AntwortZitat

Am WE wollte ich mal kurz die Schusskollision weiter entwickeln und die entsprechende Explosion des Items (der Öltank) einfügen. Leider habe ich hier massive Schwierigkeiten auf mehreren Ebenen bekommen. Zunächst wollte ich die Kollisionsabfrage im VBI machen und im Hauptprogramm dann die weiteren Schritte der Erkennung der genauen Position und dann die Explosion einfügen. Beides funktionierte zunächst nicht so richtig und ich dachte, es müsse auch in den VBI komplett mit rein. Das habe ich dann auch umgesetzt - und dabei feststellen müssen, daß er die Kollision nicht immer erkennt - ein Muster habe ich dabei nicht evaluieren können... dann kam noch die Schwierigkeit, die genaue Position des Tanks mit dem Missile zu koordinieren. Das ist in meinem Programm nicht so einfach, da der Missile eine volle Positionsauflösung hat und die Landschaft aus Charactern (8bit) aufgebaut ist. Ich muss also die x- und y-Position der Missiles zunächst umrechnen (teilen durch 8 in y und teilen durch 4 in x) und kämpfe noch mit einem Rundungsfehler.... das Teilen durch 8 geht mit drei ROR-Anweisungen! Am Ende ist das Timing und wohl auch der Zusatzcode im VBI zu lang und gestern endlich kam der Durchbruch, wo ich es stabil geschafft habe, den Code für die Explosion im Hauptprogramm unterzubringen - im VBI gibt es zu viele Timing-Probleme. Mein nächstes Projekt werde ich ganz anders strukturieren - das steht schon fest. Auch werde ich dann wohl mit einer ganz anderen Auflösung und Matrix arbeiten - das bringt zwar mehr Probleme was Speicher und Scrolling angeht, erleichtert aber mutmaßlich viele andere Dinge....

Ich frage mich auch zunehmend, ob es Sinn macht, den Code hier reinzustellen, denn der wird immer umfangreicher und unübersichtlicher trotz der Kommentare. Hier hätte ich gerne ein kurzes Feedback...

Liebe Grüße Peter

AntwortZitat

Moin!

Spontan würde ich vorschlagen auf Github den Quellcode zu posten. Dort lägen dann immer alle aktuellen Files die Du nutzt und man kann jederzeit sich dieses herunterladen. Jedoch kenne ich mich mit Github nicht aus, ob und wie schwer es ist dort den Code hochzuladen.

Ansonsten hätte ich schon Interesse an den Quellcode. Die Kollision und vorallem die Identifizierung des getroffenen Objekts würden mich sehr interessieren 🙂

Der Quellcode kann nicht genug Remarks enthalten... dass merkt man aber erst, wenn man selber nach 3-4 Monaten etwas sucht 😁

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

... mit Github kenne ich mich auch nicht so aus ...ich denke mal darüber nach! Mit den Remarks hast du absolut Recht! Da muss ich noch viel mehr machen!!

Das Objekt nach der Kollision zu identifizieren geht jetzt ganz gut! Du hast ja die x- und y-Position des Missile zum Zeitpunkt des Treffers. Diese Werte auslesen und sichern. Wenn du - so wie in diesem Projekt - mit Graphics 0 arbeitest (Zeile hat 40 Character a 8 Bit und Spalte hat 24 Character a 8 Bit), dann musst du für die x-Position des Missile zunächst 48 subtrahieren und dann mittels durch 4 teilen. Die y-Position des Missile (oder Players) bestimmst du für die Kollision indem du zunächst 32 subtrahierst und dann durch 8 teilst ... das Problem nun ist: Man weiß gar nicht, ob du den linken, rechten Rand oder die Mitte des Objektes getroffen hast... entsprechend hast du nie eine ganz genaue horizontale Position... das Problem habe ich noch nicht gelöst -> man müsste hier die Umgebung des Treffers abfragen bis eine Leerstelle kommt und dann hat man die genaue Position des Objektes ...

AntwortZitat

Ich habe jetzt tatsächlich gerade eben mir die Mühe gemacht die Ränder abzufragen und entsprechend dann die Position zu korrigieren:

      dey
      lda (var2),y
      sta var8
      iny
      iny
      lda (var2),y
      sta var9
      dey
      dey

      #if .byte var8=#0 .and .byte var9>#0
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0
      dey
      #end

      lda #45
      sta (var2),y
      iny
      sta (var2),y
      iny
      sta (var2),y

in var2 steht die Bildschirmadresse mit bereits korrekter y-Position in y steht die x-Position beim Treffer des Missiles nach Korrektur (-48 /4) in var8 geht der rechte Rand rein in var9 geht der linke Rand rein entsprechend verschiebe ich die x-Position um eins nach rechts oder links - oder gar nicht (mein Objekt ist 3 breit). Lda#45 ist nur eine Hilfszahl - später baue ich hier die Explosion rein!!

AntwortZitat

jetzt habe ich noch den y-Wert - also die vertikale Position der Kollision abgefragt und entsprechend korrigiert. Die Position am Item - also da wo die Explosion des Items bei Kollision mit dem Schuss stattfinden soll ist jetzt immer definiert und an gleicher Stelle - dafür habe ich jetzt tatsächlich erheblich Zeit und Code verwendet und frage mich natürlich, ob das nicht viel viel einfacher geht... bestimmt!! Aber egal, dieser Code und die entsprechende Logik stammt von mir und - hurra - funktioniert tadellos! Nach ca. 4 Tagen verzweifelten Kampfes 😉 Der Subroutinencode:

    kollitem
              ;var8 unveränderter Bildschirmanfang      
      lda yschuss1  ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
      sec
      sbc #32
      clc
      ror
      clc
      ror
      clc
      ror
      sta yschuss1  ;y-Position in das x-Register schreiben
      tax 
      dex       ; und einen abziehen

      lda xschuss1  ;x-Position -48 (sichtbarer Bereich)und /4
      sec
      sbc #48
      clc
      ror
      clc
      ror
      tay       ;in y geht die x-Position
      sec
      mva var1 var2   ;holen der Bildschirmadresse -> var2
      mva var1+1 var2+1
      clc
@     
      lda var2    ;jetzt die y-Position auf die richtige Höhe stellen
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dex
      bpl @-      ;die y-Position steht in x - Addition von x Zeilen
@     
      dey       ;die korrekte x-Position einstellen
      lda (var2),y  ;linken Rand checken
      sta var8    
      iny
      iny
      lda (var2),y  ;rechten Rand checken
      sta var9
      dey
      dey

      #if .byte var8=#0 .and .byte var9>#0  ;Position nach rechts anpassen 
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0  ;Position nach links anpassen
      dey
      #end

      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      iny
      iny
      lda (var2),y
      sta var9
      dey
      dey

      #if .byte var8=#0 .and .byte var9>#0
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0
      dey
      #end

      lda (var2),y    ;Korrektur der y-Position
      sta var8      ;in var8 aktuelle BS-Position
      sec
      lda var2      ;eins drüber - bleibt wenn var2 zu tief
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y    ;lade Bildschirminhalt eins drüber
      sta var9      ;das geht in var9 rein

      #if .byte var8>#0 .and .byte var9=#0  ;alte Position var2 
      clc                   ;wiederherstellen
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0  ;alte Position var2
      clc                   ;eins runter
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end

      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      sec
      lda var2
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y
      sta var9

      #if .byte var8>#0 .and .byte var9=#0
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0
      clc
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
                ;ab hier stimmt die Position des Items
                ;in der Variable y für x-Position
                ;und in var2 für die y-Position 
      lda #45
      sta (var2),y
      iny
      sta (var2),y
      iny
      sta (var2),y


      mva #2 hitclr

      mva #0 kollm1 


      rts

Dieser Code funktioniert auch für alle Kollisionen und steht entsprechend als Subroutine... was folgt jetzt: Bislang habe ich ja nur eine Dreierreihe als Simulation der Explosion geprintet - jetzt kommt die komplette Überschreibung des Items und dann die Animation dieser Explosionswolke... Ich überlege noch, ob ich das folgendermaßen mache: Entweder printe ich hintereinander verschiedene Werte in das Gebiet des Items - so daß es animiert aussieht. Oder ich lösche das Items komplett und überlagere das Gebiet mit Player4, der selber eine Animation einer explodierenden Wolke darstellt. Problem hierbei ist, wenn ich mehrere Explosionen gleichzeitig darstellen muss.

AntwortZitat

Hallo!

Ich habe mal gehört (gefährliches Halbwissen), dass man Berechnungen möglichst vermeiden sollte.

So würde man eine Tabelle mit 40 Werten nehmen wo immer der erste Wert für Gr. 0 -X drin steht. Also z.B. 48, 52, 56, 60... und nun vergleicht man den X-Wert des Missels mit der Tabelle. Bei Position 5 ein Match also ist im X-Wert eine 5 für Gr. 0. Das gleiche macht man im Y-Bereich und erhält eine Wandlung der X/Y- Spriteposition zu X/Y-Gr.0-Position. Eine Schleife mit einem kleinem Vergleich soll wohl schneller sein also eine Berechnung.

Aber wie gesagt, ich weiß es selbst nicht wirklich.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Hi Janko, vielen Dank für diesen Hinweis - in der Tat habe ich über genau so eine Tabelle auch nachgedacht und hätte das auch so gemacht. Teilen durch 4 bzw. 8 erschien mir aber machbar durch einfache Bitrotation und funktioniert auch ganz gut. Die Größe der Tabelle hat mich etwas abgeschreckt!!

Was dann heute als echter Pferdefuss noch auftrat war dann die Tatsache, dass mein Item (also zB der Tank) ja deutlich breiter ist, als mein Schuss und ich also gar nicht so genau weiß, wo mein Schuss gelandet ist - es sei denn (fällt mir gerade zur Sekunde als Idee ein) ich gestalte die Oberfläche des Items von der Farbe her unterschiedlich - dann bekomme ich einen jeweils anderen Wert für die Kollision und kann das auch nutzen... nun ja, jetzt habe ich die entsprechenden Abfragen aufwendig programmiert und es funktioniert stabil - lass ich jetzt mal!!

Für das nächste Projekt werde ich das direkt etwas anders konzipieren....

AntwortZitat

... weiter gehts mit meinem Projekt! Ich stelle auf Gr. 7 mit 4 Farben um und werde zunächst die Landschaft anpassen müssen. Hier mal ein erstes Video mit dem Vergleich: Neu links und Alt rechts.... Die Landschaft links ist natürlich hinsichtlich Form und Farbe noch nicht angepasst, sehr schön kann man hier aber den direkten Vergleich sehen zwischen Gr.0 40x24 Textgrafik (980 Bit) zu Gr.7 40x80 Bitmapgrafik (3200)

scrolvergleich.mov

Anhänge:
AntwortZitat

Vorweihnachtszeit = viel Arbeit = wenig Zeit zum programmieren... Aber ich habe heute mich um die Farben gekümmert und bin dabei das Programm auf die neue Grafik umzustellen.

Das wird jetzt recht aufwendig, da doch einiges an Code komplett neu muss. Ich will den Bildschirm in 16x16 Byte Blöcken einteilen, dabei brauche ich dann für einen kompletten Bildschirm nur einen Speicherbedarf von 200 Byte bei einer Auflösung von 160x80 mit 4 Farben. Das schafft die CPU noch ganz gut zu scrollen und sieht flüssig aus. Die Matrix wird dann praktisch 20x10 sein und in dieser Matrix sind dann die Bildschirmdaten hinterlegt, die auf den sichtbaren Bildschirm zu printen sind. Beim Printen passiert direkt das scrolling... mit einem Interrupt kann ich z.B. ständig die Matrix ändern und so Teile des Bildschirms animieren... so der Plan! Hoffentlich überlaste ich den Rechner damit nicht 😉 Wir werden sehen.... wenn es geht, könnte das recht cool werden...

Anbei noch der aktuelle Stand, wo aber die Landschaft noch nicht wesentlich angepasst ist - hier läuft zunächst noch eine Testlandschaft, die sich wiederholt. Auch die Items sind noch nicht angepasst. Viel Arbeit noch 😉 aber ich habe ja Zeit....

LG und ein frohes Fest uns allen!! Peter

rtp2.MOV

Anhänge:
AntwortZitat

... gerade habe ich nun die FUEL-Tanks optisch angepasst und die komplette Animation der Explosion generiert. Dafür brauche ich 3x12 = 36 Charakter! Nun grübel ich allerdings schon seit Tagen, wie ich diese Explosion am besten umsetze. Eine richtig einfache Lösung habe ich noch nicht gefunden - ein denkbarer Ansatz, den ich gerade verfolge ist relativ aufwendig zu programmieren. Vorweg: Einfach die Charakter ändern geht nicht, denn dabei würden sich ja dann z.B. alle Tanks entsprechend animieren - also explodieren und nicht nur der, der getroffen wurde. Es hilft nichts: Ich muss die Kollision abfragen, die ganz genaue Position des getroffenen Tanks bestimmen, diesen dann mit der ersten Explosionssequenz überschreiben, beim scrolling muss ich die Position des Tanks entsprechend weiterschreiben, damit die 2. und 3. und dann 4. Sequenz der Explosion auf die entsprechende Stelle geschrieben werden kann. Das muss ja auch 2-4 x zugleich auf dem Bildschirm ablaufen können, denn man kann ja mehr als immer nur einen Tank bzw. Item treffen. Vielleicht hat jemand hier noch eine bessere Idee...

Hier noch eine mov-Datei mit dem aktuellen Stand... Sobald ich den Code für die Explosion drin habe, kommen die nächsten Items und dann baue ich die Landschaft weiter. Dann stelle ich auch wieder den aktuellen Code rein! Allen eine frohe Weihnacht und bis bald! Gruß Peter

IMG_4114.MOV

Anhänge:
AntwortZitat

Da Du nun doch den Charmode nutzt...

Für die Explosionen nutze nicht einfach 36 Zeichen, sondern nutze nur die Zeichen, die für denTank nötig sind. Die Explosion wird dann erzeugt, indem die entsprechenden Zeichen mit dem neuen Werten direkt verändert werden. So äußerst Du Platz im Font für möglichst viele Sachen.

Aber Du musst dann natürlich mehr Dinge kopieren.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

hmmmm.... also ein Tank besteht bei mir aus 4 Reihen a 3 Character - also insgesamt 12 Character für den Öltank. Der Öltank ist das größte Item - die Explosion muss also auch 12 Character haben, animiert 3x12 also 36. Klar könnte ich das mit 12 machen und die Phasen reinkopieren - gute Idee - das Problem ist dann aber wenn ich (und das kommt vor) zwei oder sogar 3 Items abballere, die dann auch in unterschiedlichen Phasen explodieren und dabei auch noch hochgescrollt werden müssen weil das Spiel ja weiterläuft. Da hänge ich gerade.... Jede Lösung erscheint von nicht unerheblichen Programmieraufwand. Da warte ich noch auf die Eingebung, wie ich das viel leichter lösen kann ...

AntwortZitat

Hallo!

Ich weiß nicht wieviel Platz Du noch in Deinem Char-Set hast, aber Du könntest festlegen, dass nur 4 Tanks gleichzeitig vorhanden sein dürfen und vergibst für jeden Tank dann seine eigenen Zeichensequenz. So musst Du 48 Zeichen für 4 Tanks vorhalten, kannst dann aber jeden der 4 Tanks einzeln animieren.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

daran habe ich auch schon gedacht, aber ich werde nicht nur Tanks haben, sondern noch weitere Items - und dann wird es irgendwann knapp im Zeichensatz! Ich habe ja nur 128...

AntwortZitat

Ja, aber wenn nur 4 Items gleichzeitig sichtbar sind, kannst Du mit den Zeichen auch andere Items darstellen. Je nach Scrollposition.

Mein 600XL ist virenfrei!

AntwortZitat

Die letzten Tage habe ich immer wieder an der Explosion gearbeitet - und dabei festgestellt, daß es viel viel schwieriger ist, als gedacht. Die Animation für eine Explosion ist zunächst völlig ausreichend, da mein Raumschiff gar nicht so oft hintereinander schießen kann - zwei Tanks gleichzeitig zur Explosion zu bringen ist dabei fast unmöglich. Dann habe ich viel mit dem Timing experimentiert und entweder läuft die Explosion zu schnell ab und man sieht die Phasen gar nicht, oder zu langsam, wenn ich es in den Code aufwendig in verschiedenen Phasen zwischen Feinscroll und Grobscroll integriere. Die Explosion in den VBI zu bringen läuft auch zu schnell - hier könnte man mit ein wenig Programmieraufwand das Zeittiming für die Explosion vielleicht noch besser hinbekommen. Ich habe es jetzt aber erstmal einfacher gelöst: Die Explosion mit der Animation läuft direkt hintereinander ab mit einem kleinen Zeitdelay, was man leider dann im Spiel merkt, da es während der animierten Explosion zu einem kleinen Stop kommt. Ich lasse das jetzt aber erstmal so und mache endlich mit den anderen Items weiter und vor allem baue ich jetzt die Landschaft weiter aus... Gruß Peter phobos.MOV

Anhänge:
AntwortZitat

ich war fleißig, auch wenn man es vielleicht nicht so sehr sieht!! Zunächst habe ich die Explosion implementiert, die Landschaft und die Charakter weiter ausgebaut - hier fehlen noch ein paar Landschaftsteile. Dann habe ich die Anzeige mit Titel, Score, Fuel incl. Laufleiste für den Fuel implementiert. Ich musste den Aufbau der letzten Reihe erweitern, was mich viel Schweiß gekostet hat - das war nötig weil ich die Randbegrenzung komplettieren wollte / musste. Danach hatte ich ganz unerklärliche Ruckelartefakte - daran habe ich jetzt fast 2 Tage gesessen... ich dachte schon, daß die CPU langsam an die Grenze kommt und der VBI Störartefakte reinhaut... alles musste runterreduziert werden, ohne Erfolg. Am Ende war es die Displaylist. Eine kleine Anpassung und der Ruckler war wieder raus ... omG !!!! Programmieren ist manchmal wie ein Krimi. Jetzt baue ich so langsam die Landschaft weiter aus - wie man sieht auf dem Video gibt es noch eine Menge an kleineren Fehlern. Warum nur bekomme ich diesen grünen Balken links zusätzlich rein... Der Code wird immer länger und unübersichtlicher trotz Dokumentation... noch komme ich aber klar! Aber jetzt bloß keine zu lange Pause machen. Ich stelle gerne den gesamten Code hier online und wer möchte kann selber daran rumfummeln... ob jemand da aber noch durchsteigt .. keine Ahnung!! Jetzt noch eine kleine mov - Datei - und wie gesagt: Bei Interesse stelle ich den Code hier rein! Es ist noch viel zu tun.... 😉

rtp.MOV

Anhänge:
AntwortZitat

here we go... 😉

Hauptprogramm:





      org $2000

      icl '../hardware.txt'
      icl '../header.txt'
      icl 'character.asm'
      icl 'lands.asm' 

dlist     .byte 112,112,112,100
      .byte 30,75
      .byte 36,36,36,36,36,36,36,36,36,36,36,36
      .byte 36,36,36,36,36,36,36,36,36,4,4,4,4,4
      .byte 65,32,156

pm1     .byte 0,24,60,36,36,126,126,255,219,219,129,129,129,0

pm41    .byte 0,28,28,8,8,0,4,0,0,0,0,0,0,0
      .byte 0,28,28,24,8,8,4,4,0,0,4,0,8,0
      .byte 0,28,24,28,24,8,4,8,8,4,0,0,0,0

mi1     .byte 3,3,3,3     
mi2     .byte 12,12,12,12
mi3     .byte 12,12,12,12
mi4     .byte 12,12,12,12

      .proc main

main1   jsr displaylist ;Subroutine Displaylist-Aufbau
      mva #30 yposp1
      mva #120 xposp1
      mva #42 yposm1
      mva #0 xposm1
      mva #94 yposm2
      mva #100 xposm2
      mva #0 tank1x
      mva #0 tank1y
      mva #151 fuelzaehleritem
      mva #0 fuelzaehler
      jsr text

Start1    mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
      mva #192 gprior ;GTIA Modus 3 
      mva #15 color3  ;Schriftfarbe 
      mva #218 color1 ;Gelb
      mva #154 color0 ;Blau
      mva #52 color2  ;Rot
      mva #180 color2 ; Grün
      mva #0 color4 ;Hintergrundfarbe
      lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1

      ; Player vorbereiten und initialisieren
      lda ramtop
      sec
      sbc #16
      sta pmbase
      clc
      adc #3
      sta miss1+1
      adc #1
      sta play1+1
      adc #3
      sta play4+1
      lda #9
      sta play4
      mva #62 sdmctl
      mva #56 pcolr0
      mva #56 pcolr1
      mva #142 pcolr2
      mva #142 pcolr3
      mva #1 gprior
      mva #3 gractl
      mva #1 sizep0
      mva #1 sizep1
      mva #0 sizem
      mva #0 rechts
      mva #2 hitclr
      mva #48 blink

main2   mva <lands var6
      mva >lands var6+1
      mva #0 kollp0
      ldy #255        ;Speicher Player 1 leeren
      lda #0
      sta play1
@     sta (play1),y
      sta (play4),y
      dey
      bpl @-
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      ;lda pm41,x
      ;sta (play4),y
      iny
      inx
      cpx #14
      bne @-
      clc
      ldy #0
      ldx #0
@     lda mi1,x
      sta (miss1),y
      iny
      inx
      cpx #2
      bne @-
      lda xposm1
      sta p0pf
      lda xposm2
      sta p1pf
      ldx #>vbinter     ;VB-Interrupt VektorHi
      ldy #<vbinter     ;VB-Interrupt VektorLo
      lda #7          ;Deferred Mode mit lda #7 festlegen
      jsr setvbv        ;Vektor für die eigene Routine über setvbv eintragen

hauptprogramm

      clc
      lda kollp0
      cmp #1
      bcc @+
      jsr kollision
      mva #0 kollp0
@     jsr letztereihe     ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)  
      jsr feinscroll      ;Feinscroll Bildschirm1 ausführen (sichtbar)    
      mva #$30 var1     ;var1 auf 30000 ($7530) setzen
      mva #$75 var1+1
      mva #$E4 var2     ;var2 auf 31460 ($7AE4) setzen
      mva #$7A var2+1
      jsr grobscroll      ;Bildschirm1 kopieren + grobscroll
      mva #$0C var1     ;var1 + var2 auf 31500 ($7B0C) setzen
      mva #$0C var2
      mva #$7B var1+1
      mva #$7B var2+1 
      jsr umschalten
      inc fuelzaehleritem
      lda fuelzaehler
      tax
      lda fuelzaehleritem
      sta 31043,x
      sta 32543,x
      #if .byte fuelzaehleritem=#155
      mva #151 fuelzaehleritem
      inc fuelzaehler
      #end
      #if .byte fuelzaehler>#200
      mva #0 fuelzaehler
      #end
      #if .byte fuelzaehler=#20
      mva #52 color3
      #end
      #if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
      jmp main1       ;Fuel zuende Neustart
      #end
      mva #0 kollm1
      mva #0 kollm2     ;umschalten auf Bildschirm2 - Bildschirm2 wird sichtbar 
      jsr letztereihe
      jsr feinscroll      ;Feinscroll Bildschirm2 ausführen (sichtbar)            
      mva #$08 var2     ;var1 auf 29960 ($7508) setzen
      mva #$75 var2+1
      mva #$0C var1     ;var2 auf 31500 ($7B0C) setzen
      mva #$7B var1+1
      #if .byte kollges=#4
      mva #15 color3
      sec
      lda fuelzaehler
      sbc #10
      sta fuelzaehler 
      tax
      mva #151 fuelzaehleritem
      clc
      lda fuelzaehleritem
@     sta 31043,x
      sta 32543,x
      inx
      cpx #36
      bne @-
      jsr kollitem
      mva #0 kollges
      #end
      mva #$08 var2     ;var1 auf 29960 ($7508) setzen
      mva #$75 var2+1
      mva #$0C var1     ;var2 auf 31500 ($7B0C) setzen
      mva #$7B var1+1
      jsr grobscroll      ;;Bildschirm2 kopieren + grobscroll
      mva #$30 var1     ;var1 + var2 auf 30000 ($7530) setzen
      mva #$30 var2
      mva #$75 var1+1
      mva #$75 var2+1
      ;mva #1 delay
      jsr umschalten      ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar
      inc fuelzaehleritem
      lda fuelzaehler
      tax
      lda fuelzaehleritem
      sta 31043,x
      sta 32543,x
      #if .byte fuelzaehleritem=#155
      mva #151 fuelzaehleritem
      inc fuelzaehler
      #end

      ;Ende der Bildschirmausführung / Kontrolle Durchläufe
      sec
      lda #40 ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
      sbc var6+1
      bpl @+
      jmp start1      ;Stop hier
@   
      jmp hauptprogramm       ;weiter

      .endp

      ; _____________________________________________________________________________________
      ;
      ; ---------------------------- S U B R O U T I N E N ----------------------------------
      ; _____________________________________________________________________________________


                ;vertical blank interrupt für Joystick / PM

vbinter     
      pha
      txa
      pha
      mva #0 atract     ;Bildschirmschoner aus
      inc blink
      lda blink2
      adc #20
      sta blink2
      clc         ;Kollisionen abfragen
      lda p0pf
      cmp #1
      bcc @+
      mva #1 kollp0
@     
      clc         ;Joystickabfragen Player1
      lda stick0
      cmp #15       ;keine Joystickaktion
      bcs @+
      cmp #14
      bcs nachob
      cmp #13
      bcs nachun
      cmp #11
      bcs nachli
      cmp #10
      bcs nachliob
      cmp #9
      bcs nachliun
      sec
      cmp #7
      bcs nachre
      cmp #6
      bcs nachreob
      cmp #5
      bcs nachreun
@     jmp write
nachre    clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp write
nachreun
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachun
nachreob
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachob
nachli    sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp write
nachliun
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachun
nachliob
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachob
nachob
      dec yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
nachun
      inc yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
      clc
write   
      lda xposp1          ;Blinkabschnitt
      sta hposp0
      adc #2
      sta hposp3
      #if .byte blink<#64     ;Blink links
      ldy yposm3
      lda #0
      sta (miss1),y
      mva hposp0 xposm3
      ldy yposp1
      lda #48
      iny 
      iny
      iny
      iny
      iny
      iny
      sta (miss1),y
      mva xposp1 p2pf
      mva xposp1 xposm3
      sty yposm3
      #end
      #if .byte blink>#63 .and .byte blink<#128 ;Blink rechts
      ldy yposm3
      lda #0
      sta (miss1),y
      ldy yposp1
      lda #192
      iny 
      iny
      iny
      iny
      iny
      iny
      sta (miss1),y
      lda xposp1
      adc #13
      sta p3pf
      mva xposp1 xposm3
      sty yposm3
      #end
      #if .byte blink>#127 .and .byte blink<#192  ;Blink links
      ldy yposm3
      lda #0
      sta (miss1),y
      mva hposp0 xposm3
      ldy yposp1
      lda #48
      iny 
      iny
      iny
      iny
      iny
      iny
      sta (miss1),y
      mva xposp1 p2pf
      mva xposp1 xposm3
      sty yposm3
      #end
      #if .byte blink>#191 .and .byte blink<#255  ;Blink rechts
      ldy yposm3
      lda #0
      sta (miss1),y
      ldy yposp1
      lda #192
      iny 
      iny
      iny
      iny
      iny
      iny
      sta (miss1),y
      lda xposp1
      adc #13
      sta p3pf
      mva xposp1 xposm3
      sty yposm3
      #end

      ;---------- Abfrage Feuerknopf und Routine Schuss links-------

      #if .byte strig0<#1 .and .byte feuer3=#0
      #if .byte feuer5=#0 .or .byte feuer5>#180
      mva #1 feuer1
      mva #1 feuer3
      mva xposp1 p0pf
      mva xposp1 xschuss1
      lda yposp1
      adc #9
      sta feuer2
      #end
      #end
      #if .byte feuer1=#1   
      ldy feuer2
      iny
      iny
      lda #0
      sta (miss1),y
      sty feuer2
      iny
      iny
      lda #3
      sta (miss1),Y
      mva m0pf kollm1
      #if .byte kollm1=#4
      mva kollm1 kollges
      mva feuer2 yschuss1
      #end
      #if .byte kollm1>#2
      mva #211 feuer2
      #end
      #if .byte feuer2>#210
      mva #0 feuer1
      mva #0 feuer2
      lda #0
      sta (miss1),y
      #end
      #end

      ;-------------------------------------------------------------

      ;---------- Abfrage Feuerknopf und Routine Schuss rechts-------   
      #if .byte strig0<#1 .and feuer3=#1
      #if .byte feuer2=#0 .or .byte feuer2>#180
      mva #1 feuer4
      mva #0 feuer3
      lda xposp1 
      adc #13
      sta p1pf
      sta xschuss1
      lda yposp1
      adc #9
      sta feuer5
      #end
      #end
      #if .byte feuer4=#1   
      ldy feuer5
      iny
      iny
      lda #0
      sta (miss1),y
      sty feuer5
      iny
      iny
      lda #12
      sta (miss1),Y
      mva m1pf kollm2
      mva m1pf kollm2
      #if .byte kollm2=#4
      mva kollm2 kollges
      mva feuer5 yschuss1
      #end
      #if .byte kollm2>#1
      mva #211 feuer5
      #end
      #if .byte feuer5>#210
      mva #0 feuer4
      mva #0 feuer5
      lda #0
      dey
      sta (miss1),y
      iny
      sta (miss1),y
      #end
      #end
      ;-------------------------------------------------------------
      ldy yposp1  
      clc
      #if .byte blink2>#0 .and .byte blink2<#75
      ldx #0
      #end
      #if .byte blink2>#75 .and .byte blink2<#160
      ldx #14
      #end
      #if .byte blink2>#160 .and .byte blink2<#255
      ldx #28
      #end
      dey
      mva #0 lms2
@           
      lda pm41,x
      sta (play4),y
      iny
      inx
      inc lms2
      lda lms2
      cmp #14
      bne @-
      mva #2 hitclr
      pla
      tax
      pla
      jmp xitvbv      ;vb-interrupt wird über xitvbv beendet!!

      ; -------------------------------------------------------------------------------------

kollision
      ldx #0
      clc
@     inx
      cpx #255
      bcc @-
      rts

      ; -------------------------------------------------------------------------------------

umschalten
      ldy #4        ;Bildschirme umschalten von unsichtbar auf sichtbar 
      mva sdlstl var5
      mva sdlstl+1 var5+1
      lda var1
      sta (var5),y
      iny
      lda var1+1
      sta (var5),y
      rts

      ; -------------------------------------------------------------------------------------

wartes    
      clc
        ldx delay ; Warteschleife
st      lda RTCLOK+2    
wa      cmp RTCLOK+2    
          beq wa    
          dex            
          bpl st 
          rts

          ; -------------------------------------------------------------------------------------

feinscroll
      ldy #1
      mva #0 delay
@     jsr wartes
      sty vscrol
      iny
      cpy #8
      bne @-      
      rts

          ; --------------------------------------------------------------------------------------

grobscroll  
      ;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile

      ldx #22
@     ldy #$28
      clc
@     lda (var1),y 
      sta itemex
      #if .byte itemex=#68
      jsr fuel
      #end
      sta (var2),y
      dey
      bpl @-
      clc
      lda var1
      adc #$28
      sta var1
      bcc @+
      inc var1+1
@     clc
      lda var2
      adc #$28
      sta var2
      bcc @+
      inc var2+1      
@     clc
      dex
      bpl @-3
      rts

      ; -------------------------------------------------------------------------------

displaylist
      ; initialisiere die Displaylist
      mva sdlstl var5
      mva sdlstl+1 var5+1
      ldy #0
      clc
@     lda dlist,y
      sta (var5),y
      iny
      cpy #34
      bne @-
      rts

      ; ---------------------------------------------------------------------------------------

letztereihe
      ;Die letzte Reihe printen 
      ;Start der letzten Reihe bei var1 - Line 22
      ;in Var6 (+1) wird die Position von lands gespeichert
      ;in Var5 gehen Infos der Boarderanzahl rein
      ;in y ist der Zähler für letzte Reihe
      ;x wird als Zähler fürs printen benutzt

      lda var1+1
      ;sta var8+1
      ;sta var7+1
      lda var1
      ;sta var8
      ;sta var7
      adc #112
      sta var1
      inc var1+1
      inc var1+1
      inc var1+1
      ldy #0
      clc
      lda (var6),y  ;Boarderanzahl 1 holen
      sta var5    ;Boarderanzahl 1 in var5 speichern
      jsr var6up
      lda (var6),y  ;Boarderart 1 holen
      ldy var5    ;Zeilenzählen in y übertragen
@     sta (var1),y  ;Boarder1 printen
      dey
      bpl @-      
      jsr var6up
      adc #0
      sta var6+1
      lda (var6),y  ;Boarderanzahl 2 holen
      tax
      jsr var6up
      lda (var6),y  ;Boarderart 2 holen
      ldy var5
@     iny      
      sta (var1),y  ;leer printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda (var6),y  ;Rand Boarder2 holen
      inc var5    ;Zeilenzähler eins weiter
      ldy var5  
      sta (var1),y  ;Rand Boarder1 printen
      jsr var6up
      inc var5
      lda(var6),y   ;leer holen
      tax
      lda #0
      ldy var5      
@     iny      
      sta (var1),y  ;leer printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Rand Boarder3 holen
      ldy var5
      iny
      sty var5
      sta (var1),y  ;Rand Boarder3 printen
      jsr var6up
      lda(var6),y   ;Boarder4 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder4 printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Boarder5 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder5 printen
      dex
      bpl @-
      jsr var6up
      lda (var6),y  ;Sonderitem holen
      sta var5    ;Item in Var5 speichern
      jsr var6up
      #if .byte var5=#56  ;Öltank printen
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Fueltank printen
      #end
      jsr var6up
      mva #0 vscrol
      sec
      lda tank1y
      sbc #40
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      lda tank1x
      tay
      mva #0 var5
      rts

var6up    clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1
      rts

      ; --------------------------------------------------------------------------------------

fuel    sec       ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
      lda var1
      sbc #160
      sta var2
      lda var1+1
      sbc #0
      sta var2+1
fuelex    lda var5
      sta (var2),y  ;1
      inc var5
      lda var5
      iny
      sta (var2),y  ;2
      inc var5
      lda var5
      iny
      sta (var2),y  ;3
      clc
      lda var2
      adc #41
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dey
      inc var5
      lda var5
      sta (var2),y  ;4
      dey
      inc var5
      lda var5
      sta (var2),y  ;5
      dey
      inc var5
      lda var5
      sta (var2),y  ;6
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      inc var5
      lda var5
      sta (var2),y  ;7
      inc var5
      lda var5
      iny
      sta (var2),y  ;8
      inc var5
      lda var5
      iny
      sta (var2),y  ;9 
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      inc var5
      lda var5
      sta (var2),y  ;10
      dey
      inc var5
      lda var5
      sta (var2),y  ;11
      dey
      inc var5
      lda var5
      sta (var2),y  ;12
      tya
      rts

      ; ------------------------------------------------------------------------------


kollitem          ;Kollisionsroutine
              ;var8 unveränderter Bildschirmanfang      
      lda yschuss1  ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
      sec
      sbc #32
      clc
      ror
      clc
      ror
      clc
      ror
      sta yschuss1  ;y-Position in das x-Register schreiben
      tax 
      dex       ; und einen abziehen
      lda xschuss1  ;x-Position -48 (sichtbarer Bereich)und /4
      sec
      sbc #48
      clc
      ror
      clc
      ror
      tay       ;in y geht die x-Position
      sec
      mva var1 var2   ;holen der Bildschirmadresse -> var2
      mva var1+1 var2+1
      clc
@     lda var2    ;jetzt die y-Position auf die richtige Höhe stellen
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dex
      bpl @-      ;die y-Position steht in x - Addition von x Zeilen
@     dey       ;die korrekte x-Position einstellen
      lda (var2),y  ;linken Rand checken
      sta var8    
      iny
      iny
      lda (var2),y  ;rechten Rand checken
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0  ;Position nach rechts anpassen 
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0  ;Position nach links anpassen
      dey
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      iny
      iny
      lda (var2),y
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0
      dey
      #end
      lda (var2),y    ;Korrektur der y-Position
      sta var8      ;in var8 aktuelle BS-Position
      sec
      lda var2      ;eins drüber - bleibt wenn var2 zu tief
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y    ;lade Bildschirminhalt eins drüber
      sta var9      ;das geht in var9 rein
      #if .byte var8>#0 .and .byte var9=#0  ;alte Position var2 
      clc                   ;wiederherstellen
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0  ;alte Position var2
      clc                   ;eins runter
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      sec
      lda var2
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y
      sta var9
      #if .byte var8>#0 .and .byte var9=#0
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0
      clc
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
                ;ab hier stimmt die Position des Items (meistens)
                ;in der Variable y für x-Position
                ;und in var2 für die y-Position 
expl11    
      mva var2 tank1pos   ;y-Position für Explosion1
      mva var2+1 tank1pos+1
      mva #68 var5
      jsr fuelex
      tay
      iny
expl22    
      mva #80 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      jsr fuelex
      tay
      iny
expl33    
      mva #92 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      jsr fuelex
      tay
      iny
expl44    
      mva #104 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      jsr fuelex
      tay
      iny
      rts

      ; ------------------------------------------------------------------------------

text    ldx #0
      lda #52
      jsr prte
      inx
      lda #45
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #31
      jsr prte
      inx
      lda #52
      jsr prte
      inx
      lda #49
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #51
      jsr prte
      inx
      lda #47
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #42
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #53
      jsr prte
      inx
      lda #0
      jsr prte 
      inx
      lda #55
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #32
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #54
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #50
      jsr prte 
      inx
      lda #44
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #47
      jsr prte 
      inx
      lda #48
      jsr prte 
      inx 
      lda #0
      jsr prte      

      ldx #0    ;Fuel
      lda #46
      jsr prte2
      inx
      lda #31
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #48
      jsr prte2

      ldx #10   ;Score
      lda #53
      jsr prte2
      inx
      lda #43
      jsr prte2
      inx
      lda #50
      jsr prte2
      inx
      lda #52
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #0
      jsr prte2
      inx
      lda #160
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      ldx #23   ;Ships
      lda #53
      jsr prte2
      inx
      lda #47
      jsr prte2
      inx
      lda #33
      jsr prte2
      inx
      lda #51
      jsr prte2
      inx
      lda #53
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      ldx #0
fuellauf  
      clc
      lda fuelzaehleritem
@     jsr prte3
      inx
      cpx #36
      bne @-
      rts
prte    sta 30923,x
      sta 32423,x
      rts
prte2   sta 31003,x
      sta 32503,x
      rts
prte3   sta 31043,x
      sta 32543,x
      rts

      ; ------------------------------------------------------------------------------


      run main

lands:

;@com.wudsn.ide.asm.mainsourcefile=test.asm


      ; Aufbau der letzten Reihe:
      ; Boarder1  Boarder2 Rand1(gelb) Mitte(Leerraum) Rand2(gelb) Boarder3 Boarder4 Item(z.B. Öltank - Charakter 56)
      ; Beispiel: 3,2,4,1,5,22,6,4,2,1,1,56,11
      ; 3x BoarderArt 2 printen / 4x BoarderArt 1 printen / 1x RandArt 1 printen / 22 Leerzeichen printen
      ; 1x RandArt 6 printen, 4x BoarderArt 2 printen, 1x BoarderArt 1 printen, Öltank (56) an Stelle 11 printen
      ; Die Routine "letztereihe" verarbeitet dies kontinuierlich nach jedem Feinscroll/Grobscroll


lands   .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,2,4,2,10,22,11,4,2,1,2,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0  ;22
      .byte 6,1,5,2,10,16,11,4,1,1,1,56,9
      .byte 6,1,5,1,10,13,11,2,2,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 12,1,3,2,7,9,11,2,1,6,1,56,14
      .byte 13,1,3,1,7,8,11,2,1,6,1,0,0
      .byte 13,1,4,1,7,7,11,2,1,6,1,0,0
      .byte 13,1,5,1,10,6,11,2,1,6,1,0,0
      .byte 13,1,4,1,8,7,11,2,1,6,1,0,0
      .byte 17,1,0,8,0,7,11,2,1,6,1,0,0



      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0  ;22
      .byte 6,1,5,2,10,16,11,4,1,1,1,56,9
      .byte 6,1,5,1,10,13,11,2,2,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 12,1,3,2,7,9,11,2,1,6,1,56,14
      .byte 13,1,3,1,7,8,11,2,1,6,1,0,0
      .byte 13,1,4,1,7,7,11,2,1,6,1,0,0
      .byte 13,1,5,1,10,6,11,2,1,6,1,0,0
      .byte 13,1,4,1,8,7,11,2,1,6,1,0,0
      .byte 17,1,0,8,0,7,11,2,1,6,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0  ;22
      .byte 6,1,5,2,10,16,11,4,1,1,1,56,9
      .byte 6,1,5,1,10,13,11,2,2,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 6,1,5,1,10,13,11,2,1,6,1,0,0
      .byte 12,1,3,2,7,9,11,2,1,6,1,56,14
      .byte 13,1,3,1,7,8,11,2,1,6,1,0,0
      .byte 13,1,4,1,7,7,11,2,1,6,1,0,0
      .byte 13,1,5,1,10,6,11,2,1,6,1,0,0
      .byte 13,1,4,1,8,7,11,2,1,6,1,0,0
      .byte 17,1,0,8,0,7,11,2,1,6,1,0,0
      .byte 1,1,4,1,10,22,11,4,1,1,1,0,0

character:

 ;@com.wudsn.ide.asm.mainsourcefile=test2.asm




chr     .byte 0,0,0,0,0,0,0,0
      .byte 255,255,255,255,255,255,255,255 ;1 Color 2 (grün - alternativ)
      .byte 170,255,255,255,255,255,255,255
      .byte 255,255,255,255,255,255,255,170
      .byte 128,224,248,248,248,248,224,128
      .byte 2,11,47,47,47,47,11,2
      .byte 170,255,255,255,255,255,255,170   ;6
      .byte 128,224,224,248,248,248,254,254
      .byte 254,254,248,248,248,224,224,128
      .byte 254,254,248,248,248,224,224,170
      .byte 128,128,128,128,128,128,128,128
      .byte 2,2,2,2,2,2,2,2
      .byte 254,254,254,254,254,254,254,254   ;12
      .byte 191,191,191,191,191,191,191,191
      .byte 0,0,0,0,0,0,0,0
      .byte $e0,$e0,$ee,$ee,$ee,$ee,$e0,$e0 
      .byte $ee,$ee,$ee,$ee,$ee,$ee,$ee,$ee
      .byte $0e,$0e,$ee,$ee,$ee,$ee,$0e,$0e
      .byte $e0,$e0,$e0,$e0,$e0,$e0,$e0,$e0
      .byte $0e,$0e,$0e,$0e,$0e,$0e,$0e,$0e
      .byte $0,$0,$0,$0,$ee,$ee,$ee,$ee
      .byte $ee,$ee,$ee,$ee,0,0,0,0
      .byte $e0,$e0,$e0,$e0,$ee,$ee,$ee,$ee
      .byte 0,0,255,255,255,255,0,0     ;Fuel lauf  - 123
      .byte 0,0,63,63,63,63,0,0       ;F
      .byte 0,0,15,15,15,15,0,0       ;U  - 25
      .byte 0,0,3,3,3,3,0,0         ;U
      .byte 0,0,0,0,0,0,0,0         ;E  - 27
      .byte 1,4,4,21,85,81,64,64        ;28 -> Schiff klein
      .byte 64,16,16,84,85,69,1,1       ;29 -> Schiff klein
      .byte 0,0,0,0,0,0,$f0,$f0       ;L

      .byte 136,136,136,136,136,136,136,168 ;31 -> U
      .byte 32,136,136,136,168,136,136,32   ;32 -> 0
      .byte 32,32,32,32,32,32,32,32
      .byte 168,8,8,168,168,128,128,168   ;34 -> 2
      .byte 170,2,2,170,170,2,2,170     ;33 -> 5 
      .byte 128,136,136,170,170,8,8,8     ;36 -> 4
      .byte 170,128,128,170,170,2,2,170
      .byte 128,128,128,170,130,130,130,170 ;38 -> 6
      .byte 168,8,8,42,42,8,8,8
      .byte 170,130,130,170,170,130,130,170 ;40 -> 8
      .byte 170,130,130,170,170,2,2,2     ;41 -> 9
      .byte 160,136,136,160,160,136,136,160 ;42 -> B
      .byte 40,128,128,128,128,128,128,40   ;43 -> C
      .byte 160,136,136,136,136,136,136,160 ;44 -> D
      .byte 168,128,128,168,168,128,128,168 ;45 -> E
      .byte 168,128,128,168,168,128,128,128 ;46 -> F
      .byte 136,136,136,168,168,136,136,136 ;47 -> H
      .byte 128,128,128,128,128,128,128,170 ;48 -> L
      .byte 130,130,162,162,138,138,138,130 ;49 -> N
      .byte 32,136,136,136,136,136,136,32   ;50 -> O
      .byte 160,136,136,168,160,128,128,128 ;51 -> P
      .byte 160,136,136,168,160,136,136,136 ;52 -> R
      .byte 40,128,128,168,168,8,8,160    ;53 -> S
      .byte 168,168,32,32,32,32,32,32     ;54 -> T
      .byte 0,0,8,32,32,32,32,8         ;55 -> c
tank    .byte 0,0,0,0,15,15,53,53       ;56 -> Fuel Tank
      .byte 0,0,255,255,255,255,185,185
      .byte 0,0,192,192,252,252,111,111
      .byte 239,239,111,111,239,239,107,107
      .byte 185,185,185,185,185,185,169,169
      .byte 55,55,53,53,55,55,55,55
      .byte 15,15,0,0,0,0,2,2
      .byte 255,255,136,136,136,136,170,170
      .byte 252,252,128,128,128,128,160,160
      .byte 32,32,168,168,8,8,42,42
      .byte 8,8,170,170,8,8,42,42       
      .byte 2,2,10,10,8,8,42,42       ;67
expl1   .byte 0,0,0,32,32,8,5,1         ;68
      .byte 0,0,0,2,24,85,154,102
      .byte 0,0,64,64,0,0,66,72
      .byte 80,144,160,84,152,100,100,170
      .byte 101,153,153,86,102,106,153,153
      .byte 5,9,134,22,25,41,22,150
      .byte 166,25,25,41,86,6,5,9
      .byte 154,102,102,149,153,90,101,166
      .byte 89,84,100,164,104,80,144,144
      .byte 64,6,8,0,0,0,0,0
      .byte 150,153,89,20,2,0,0,0
      .byte 17,1,0,2,8,0,0,0          ;79
expl2   .byte 0,0,0,0,0,0,0,0         ;80
      .byte 0,0,0,0,0,0,0,0
      .byte 0,0,0,0,0,0,0,0
      .byte 4,16,128,128,64,64,64,160
      .byte 20,90,89,165,150,90,105,101
      .byte 8,8,1,1,1,2,6,5
      .byte 1,2,2,1,1,8,8,32
      .byte 149,153,170,102,85,105,24,20
      .byte 96,64,128,144,16,0,0,0
      .byte 0,0,0,0,0,0,0,0
      .byte 8,2,0,0,0,0,0,0
      .byte 0,0,0,0,0,0,0,0         ;91
expl3   .byte 0,0,0,0,0,0,0,0         ;92
      .byte 0,0,0,0,0,0,0,0   
      .byte 0,0,0,0,0,0,0,0   
      .byte 0,0,0,0,0,0,0,0   
      .byte 0,0,0,2,24,89,102,150
      .byte 0,0,0,0,2,0,0,0   
      .byte 0,0,2,0,0,0,0,0   
      .byte 169,89,90,36,0,0,0,0
      .byte 0,0,0,128,0,0,0,0   
      .byte 0,0,0,0,0,0,0,0   
      .byte 0,0,0,0,0,0,0,0   
      .byte 0,0,0,0,0,0,0,0         ;103

expl4   .byte 0,0,0,0,0,0,0,0         ;104
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0         
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 
      .byte 0,0,0,0,0,0,0,0 

      .byte 15,15,0,0,0,0,2,2
      .byte 255,255,136,136,136,136,170,170
      .byte 252,252,128,128,128,128,160,160
      .byte 32,32,168,168,8,8,42,42
      .byte 8,8,170,170,8,8,42,42
      .byte 2,2,10,10,8,8,42,42     
      .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f   ;F  - 132
      .byte $f0,$f0,0,0,$f0,0,0,0       ;F
      .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;U  - 134
      .byte $0f,$0f,$0f,$0f,$0f,$0f,$ff,$ff ;U
      .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f   ;E  - 136
      .byte $f0,$f0,0,0,$f0,0,$f0,$f0     ;E
      .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f ;L  - 138
      .byte 0,0,0,0,0,0,$f0,$f0       ;L
      .byte $44,$44,$44,$44,$40,$40,$40,$40
      .byte $04,$04,$04,$04,$44,$44,$44,$44
      .byte $44,$44,$44,$44,$04,$04,$04,$04
      .byte $30,$30,$33,$33,$33,$33,$30,$30 ;143
      .byte $33,$33,$33,$33,$33,$33,$33,$33
      .byte $03,$03,$33,$33,$33,$33,$03,$03
      .byte $30,$30,$30,$30,$30,$30,$30,$30
      .byte $03,$03,$03,$03,$03,$03,$03,$03
      .byte $0,$0,$0,$0,$33,$33,$33,$33
      .byte $33,$33,$33,$33,0,0,0,0
      .byte $30,$30,$30,$30,$33,$33,$33,$33
      .byte $33,$33,$33,$33,$30,$30,$30,$30
      .byte $03,$03,$03,$03,$33,$33,$33,$33
      .byte $33,$33,$33,$33,$03,$03,$03,$03
      .byte $20,$20,$22,$22,$22,$22,$20,$20 ;154
      .byte $22,$22,$22,$22,$22,$22,$22,$22
      .byte $02,$02,$22,$22,$22,$22,$02,$02
      .byte $20,$20,$20,$20,$20,$20,$20,$20
      .byte $02,$02,$02,$02,$02,$02,$02,$02
      .byte $0,$0,$0,$0,$22,$22,$22,$22
      .byte $22,$22,$22,$22,0,0,0,0
      .byte $20,$20,$20,$20,$22,$22,$22,$22
      .byte $22,$22,$22,$22,$20,$20,$20,$20
      .byte $02,$02,$02,$02,$22,$22,$22,$22
      .byte $22,$22,$22,$22,$02,$02,$02,$02
      .byte $10,$10,$11,$11,$11,$11,$10,$10 ;165
      .byte $11,$11,$11,$11,$11,$11,$11,$11
      .byte $01,$01,$11,$11,$11,$11,$01,$01
      .byte $10,$10,$10,$10,$10,$10,$10,$10
      .byte $01,$01,$01,$01,$01,$01,$01,$01
      .byte $0,$0,$0,$0,$11,$11,$11,$11
      .byte $11,$11,$11,$11,0,0,0,0
      .byte $10,$10,$10,$10,$11,$11,$11,$11
      .byte $11,$11,$11,$11,$10,$10,$10,$10
      .byte $01,$01,$01,$01,$11,$11,$11,$11
      .byte $11,$11,$11,$11,$01,$01,$01,$01
      .byte $10,$10,$11,$11,$11,$11,$10,$10 ;176
      .byte $11,$11,$11,$11,$11,$11,$11,$11
      .byte $01,$01,$11,$11,$11,$11,$01,$01
      .byte $10,$10,$10,$10,$10,$10,$10,$10
                          ;184 Fuel-Tank
      ;.byte 0,0,0,0,15,15,53,53      
      ;.byte 0,0,255,255,255,255,185,185
      ;.byte 0,0,192,192,252,252,111,111
      ;.byte 239,239,111,111,239,239,107,107
      ;.byte 185,185,185,185,185,185,169,169
      ;.byte 55,55,53,53,55,55,55,55      ;190
      ;.byte 15,15,0,0,0,0,2,2          ;191
      ;.byte 255,255,136,136,136,136,170,170  ;192
      ;.byte 252,252,128,128,128,128,160,160
      ;.byte 32,32,168,168,8,8,42,42
      ;.byte 8,8,170,170,8,8,42,42        
      ;.byte 2,2,10,10,8,8,42,42

header:

var1 = $a0
var2 = $a2
var3 = $a4
var4 = $a6
var5 = $a8
var6 = $b2
var7 = $b4
lms1 = $b6
lms2 = $b8
lmslo = $a0
lmshi = $a2
delay = $b0

play1 = $92
play2 = $94
play3 = $96
play4 = $98

miss1 = $c0
miss2 = $c2
miss3 = $c4
miss4 = $c6
rechts = $c8
links = $c9
xposp1 = $ca
yposp1 = $cb
joyst1 = $cc
kollp0 = $cd

xposm1 = $ce
yposm1 = $cf
xposm2 = $d0
yposm2 = $d1
xposm3 = $dc
yposm3 = $dd
kollm1 = $d2
kollm2 = $d3

feuer1 = $d4
feuer2 = $d5
yposm1hilf = $d6
feuer3 = $d7
feuer4 = $d8
yposm2hilf = $d9
feuer5 = $da
feuer6 = $db
blink = $de
blink2 = $df
ysonder = $e0
xschuss1 = $e1
yschuss1 = $e2
xschuss2 = $e4
yschuss2 = $e5
var8 = $e7
var9 = $e8
kollges = $f0
explosion1 = $f1
itemex = $f2
tank1exp = $f4
tank1pos = $f6
tank1x = $f8
tank1y = $fa
exp1 = $1900
exp2 = $1902
exp3 = $1904
exp4 = $1906
fuelzaehler = $1908
fuelzaehleritem = $1909

hardware:

LINZBS   = $0000
CASINI   = $0002
RAMLO    = $0004
TRAMSZ   = $0006
TSTDAT   = $0007
WARMST   = $0008
BOOT?    = $0009
DOSVEC   = $000a
DOSINI   = $000c
APPMHI   = $000e
POKMSK   = $0010
BRKKEY   = $0011
RTCLOK   = $0012
BUFADR   = $0015
ICCOMT   = $0017
DSKFMS   = $0018
DSKUTL   = $001a
PTIMOT   = $001c
PBPNT    = $001d
PBUFSZ   = $001e
PTEMP    = $001f
ICHIDZ   = $0020
ICDNOZ   = $0021
ICCOMZ   = $0022
ICSTAZ   = $0023
ICBALZ   = $0024
ICPTLZ   = $0026
ICBLLZ   = $0028
ICAX1Z   = $002a
ICAX2Z   = $002b
ICAX3Z   = $002c
ICAX4Z   = $002c
ICAX5Z   = $002e
ICAX6Z   = $002f
STATUS   = $0030
CHKSUM   = $0031
BUFRLO   = $0032
BUFRHI   = $0033
BFENLO   = $0034
BFENHI   = $0035
CRETRY   = $0036
DRETRY   = $0037
BUFRFL   = $0038
RECVDN   = $0039
XMTDON   = $003a
CHKSNT   = $003b
NOCKSM   = $003c
BPTR     = $003d
FTYPE    = $003e
FEOF     = $003f
FREQ     = $0040
SOUNDR   = $0041
CRITIC   = $0042
FMZSPG   = $0043
ZDRVA    = $0045
ZSBA     = $0047
ERRNO    = $0049
CKEY     = $004a
CASSBT   = $004b
DSTAT    = $004c
ATRACT   = $004d
DRKMSK   = $004e
COLRSH   = $004f
TMPCHR   = $0050
HOLD1    = $0051
LMARGN   = $0052
RMARGN   = $0053
ROWCRS   = $0054
COLCRS   = $0055
DINDEX   = $0057
SAVMSC   = $0058
OLDROW   = $005a
OLDCOL   = $005b
OLDCHR   = $005d
OLDADR   = $005e
NEWROW   = $0060
NEWCOL   = $0061
LOGCOL   = $0063
ADRESS   = $0064
MLTTMP   = $0066
SAVADR   = $0068
RAMTOP   = $006a
BUFCNT   = $006b
BUFSTR   = $006c
BITMSK   = $006e
SHFAMT   = $006f
ROWAC    = $0070
COLAC    = $0072
ENDPT    = $0074
DELTAR   = $0076
DELTAC   = $0077
ROWINC   = $0079
COLINC   = $007a
SWPFLG   = $007b
HOLDCH   = $007c
INSDAT   = $007d
COUNTR   = $007e

; hardware shadow registers
VDSLST   = $0200
VPRCED   = $0202
VINTER   = $0204
VBREAK   = $0206
VKEYBD   = $0208
VSERIN   = $020a
VSEROR   = $020c
VSEROC   = $020e
VTIMR1   = $0210
VTIMR2   = $0212
VTIMR4   = $0214
VIMIRQ   = $0216
CDTMV1   = $0218
CDTMV2   = $021a
CDTMV3   = $021c
CDTMV4   = $021e
CDTMV5   = $0220
VVBLKI   = $0222
VVBLKD   = $0224
CDTMA1   = $0226
CDTMA2   = $0228
CDTMF3   = $022a
SRTIMR   = $022b
CDTMF4   = $022c
INTEMP   = $022d
CDTMF5   = $022e
SDMCTL   = $022f
SDLSTL   = $0230
SSKCTL   = $0232
SPARE    = $0233
LPENH    = $0234
LPENV    = $0235
BRKKY    = $0236
CDEVIC   = $023a
CCOMND   = $023b
CAUX1    = $023c
CAUX2    = $023d
TEMP     = $023e
ERRFLG   = $023f
DFLAGS   = $0240
DBSECT   = $0241
BOOTAD   = $0242
COLDST   = $0244
DSKTIM   = $0246
LINBUF   = $0247
GPRIOR   = $026f
PADDL0   = $0270
PADDL1   = $0271
PADDL2   = $0272
PADDL3   = $0273
PADDL4   = $0274
PADDL5   = $0275
PADDL6   = $0276
PADDL7   = $0277
STICK0   = $0278
STICK1   = $0279
STICK2   = $027a
STICK3   = $027b
PTRIG0   = $027c
PTRIG1   = $027d
PTRIG2   = $027e
PTRIG3   = $027f
PTRIG4   = $0280
PTRIG5   = $0281
PTRIG6   = $0282
PTRIG7   = $0283
STRIG0   = $0284
STRIG1   = $0285
STRIG2   = $0286
STRIG3   = $0287
CSTAT    = $0288
WMODE    = $0289
BLIM     = $028a
TXTROW   = $0290
TXTCOL   = $0291
TINDEX   = $0293
TXTMSC   = $0294
TXTOLD   = $0296
TMPX1    = $029c
HOLD3    = $029d
SUBTMP   = $029e
HOLD2    = $029f
DMASK    = $02a0
TMPLBT   = $02a1
ESCFLG   = $02a2
TABMAP   = $02a3
LOGMAP   = $02b2
INVFLG   = $02b6
FILFLG   = $02b7
TMPROW   = $02b8
TMPCOL   = $02b9
SCRFLG   = $02bb
HOLD4    = $02bc
HOLD5    = $02bd
SHFLOK   = $02be
BOTSCR   = $02bf
PCOLR0   = $02c0
PCOLR1   = $02c1
PCOLR2   = $02c2
PCOLR3   = $02c3
COLOR0   = $02c4
COLOR1   = $02c5
COLOR2   = $02c6
COLOR3   = $02c7
COLOR4   = $02c8

; IO space
RUNAD    = $02e0
INITAD   = $02e2
RAMSIZ   = $02e4
MEMTOP   = $02e5
MEMLO    = $02e7
DVSTAT   = $02ea
CBAUDL   = $02ee
CBAUDH   = $02ef
CRSINH   = $02f0
KEYDEL   = $02f1
CH1      = $02f2
CHACT    = $02f3
CHBAS    = $02f4
CHAR     = $02fa
ATACHR   = $02fb
CH       = $02fc
FILDAT   = $02fd
DSPFLG   = $02fe
SSFLAG   = $02ff
DDEVIC   = $0300
DUNIT    = $0301
DCOMND   = $0302
DSTATS   = $0303
DBUFLO   = $0304
DBUFHI   = $0305
DTIMLO   = $0306
DUNUSE   = $0307
DBYTLO   = $0308
DBYTHI   = $0309
DAUX1    = $030a
DAUX2    = $030b
TIMER1   = $030c
ADDCOR   = $030e
CASFLG   = $030f
TIMER2   = $0310
TEMP1    = $0312
TEMP2    = $0314
TEMP3    = $0315
SAVIO    = $0316
TIMFLG   = $0317
STACKP   = $0318
TSTAT    = $0319
HATABS   = $031a
IOCB0    = $0340
IOCB1    = $0350
IOCB2    = $0360
IOCB3    = $0370
IOCB4    = $0380
IOCB5    = $0390
IOCB6    = $03a0
IOCB7    = $03b0
PRNBUF   = $03c0
CASBUF   = $03fd

; GTIA write locations
HPOSP0   = $d000
HPOSP1   = $d001
HPOSP2   = $d002
HPOSP3   = $d003
HPOSM0   = $d004
HPOSM1   = $d005
HPOSM2   = $d006
HPOSM3   = $d007
SIZEP0   = $d008
SIZEP1   = $d009
SIZEP2   = $d00a
SIZEP3   = $d00b
SIZEM    = $d00c
GRAFP0   = $d00d
GRAFP1   = $d00e
GRAFP2   = $d00f
GRAFP3   = $d010
GRAFM    = $d011
COLPM0   = $d012
COLPM1   = $d013
COLPM2   = $d014
COLPM3   = $d015
COLPF0   = $d016
COLPF1   = $d017
COLPF2   = $d018
COLPF3   = $d019
COLBK    = $d01a
PRIOR    = $d01b
VDELAY   = $d01c
GRACTL   = $d01d
HITCLR   = $d01e
CONSOL   = $d01f

; GTIA read locations
M0PF     = $d000
M1PF     = $d001
M2PF     = $d002
M3PF     = $d003
P0PF     = $d004
P1PF     = $d005
P2PF     = $d006
P3PF     = $d007
M0PL     = $d008
M1PL     = $d009
M2PL     = $d00a
M3PL     = $d00b
P0PL     = $d00c
P1PL     = $d00d
P2PL     = $d00e
P3PL     = $d00f
TRIG0    = $d010
TRIG1    = $d011
TRIG2    = $d012
TRIG3    = $d013
PAL      = $d014

; POKEY write locations
AUDF1    = $d200
AUDC1    = $d201
AUDF2    = $d202
AUDC2    = $d203
AUDF3    = $d204
AUDC3    = $d205
AUDF4    = $d206
AUDC4    = $d207
AUDCTL   = $d208
STIMER   = $d209
SKREST   = $d20a
POTGO    = $d20b
SEROUT   = $d20d
IRQEN    = $d20e
SKCTL    = $d20f

; POKEY read locations
POT0     = $d200
POT1     = $d201
POT2     = $d202
POT3     = $d203
POT4     = $d204
POT5     = $d205
POT6     = $d206
POT7     = $d207
ALLPOT   = $d208
KBCODE   = $d209
RANDOM   = $d20a
SERIN    = $d20d
IRQST    = $d20e
SKSTAT   = $d20f

; PIA
PORTA    = $d300
PORTB    = $d301
PACTL    = $d302
PBCTL    = $d303

; ANTIC write locations
DMACTL   = $d400
CHACTL   = $d401
DLISTL   = $d402
DLISTH   = $d403
HSCROL   = $d404
VSCROL   = $d405
PMBASE   = $d407
CHBASE   = $d409
WSYNC    = $d40a
NMIEN    = $d40e
NMIRES   = $d40f

; ANTIC read locations
VCOUNT   = $d40b
PENH     = $d40c
PENV     = $d40d
NMIST    = $d40f
 NMIEN_DLI = $80
 NMIEN_VBI = $40

; vector tables
EDITRV   = $e400
SCRENV   = $e410
KEYBDV   = $e420
PRINTV   = $e430
CASETV   = $e440
DISKIV   = $e450
DSKINV   = $e453
CIOV     = $e456
SIOV     = $e459
SETVBV   = $e45c
SYSVBV   = $e45f
XITVBV   = $e462
SIOINV   = $e465
SENDEV   = $e468
INTINV   = $e46b
CIOINV   = $e46e
BLKBDV   = $e471
WARMSV   = $e474
COLDSV   = $e477
RBLOKV   = $e47a
CSOPIV   = $e47d

Gruß Peter

AntwortZitat

Hallo Peter,

ich habe nur ein paar kleine Dinge geändert und auch 2, 3 Hinweise hinzugefügt. Ich denke der Unterschied ist schnell zu sehen und Du kannst das selbst nach Deinem Gutdünken ausweiten. Aber das Teilen und in Prozeduren packen hilft ungemein bei größeren Projekten. Wie man ein Label in einer anderen Prozedur ansprechen kann, sieht man bei einigen jsr fuel.fuelex aufrufen.

Bei "go lucky" und "runfast" habe ich da auch ordentlich Code in halbwegs übersichtliche Dateien packen können. So konnte ich auch viel Code von "go lucky" direkt bei "runfast" wieder verwenden. Das hat die Entwicklung enorm beschleunigt.

r2phobos.zip

Viel Spaß beim weitercoden 😉 Ich hoffe, Dir das nun ein wenig leichter gemacht zu haben. Ralf

PS: Die erste Zeile in den ausgelagerten Dateien sorgt dafür, dass man dort direkt das gesamte Programm assemblieren kann.

Anhänge:

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Guten Morgen Ralf, vielen Dank für deine Mühe und Arbeit. Größere Abschnitte sinnvoll auszulagern macht auf jeden Fall Sinn - also auch der VBI. An der DList muss ich noch ein wenig rumschrauben... wahrscheinlich kommt da auch noch ein Interrupt rein.

Der VBI ist zu lang, da muss ich noch kürzen... was unheimlich aufwendig als Code geworden ist, ist das Blinken des Raumschiffes. Das muss viel einfacher gehen. Auch mit den Schüssen bin ich nicht so ganz zufrieden - ich wollte es so programmieren, das die Schüsse nur abwechselnd ausgelöst werden können, vielleicht muss ich da noch einen anderen Weg gehen. Das Printen der letzten Reihe (ist nicht im VBI) ist zu aufwendig, das muss ich auch ändern, ich habe da auch schon eine gute Idee. Ein großer Knackpunkt ist auch die genaue Kollisionserkennung... da habe ich richtig viel Code reingesteckt und es läuft immer noch nicht 100% ig richtig. Das werde ich auch komplett umbauen. Eigentlich geht es da ja hauptsächlich um die korrekte x-Position des getroffenen Items - sowohl die x als auch die y-Position habe ich beim printen - vielleicht speicher ich das einfach zwischen und greife dann bei der Kollision darauf zurück und muss nur die y-Position ändern - die habe ich ja aber zum Zeitpunkt der Kollision........ Jetzt baue ich aber zunächst die Landschaft weiter aus und die anderen Items, damit ich die Landschaft befüllen kann - dann kümmere ich mich um die Codeverbesserungen und Fehlerbereinigungen. Ideen und Codefehler-/Optimierungsvorschläge sind auf jeden Fall gerne gesehen!

Für mich dient dieses Projekt in erster Linie, um Spaß beim programmieren zu haben und um zu lernen... wenn ich meine Anfänge im August 2021 ("Hallo Welt") mit dem Fortschritt jetzt vergleiche, dann bin ich mehr als zufrieden! LG Peter

AntwortZitat

Prodehl schrieb: ... wenn ich meine Anfänge im August 2021 ("Hallo Welt") mit dem Fortschritt jetzt vergleiche, dann bin ich mehr als zufrieden!

Das kannst Du auch sein! Respekt. 🙂 Wenn ich überlege wie oft ich mit Assembler schon angefangen habe und dann hängen geblieben bin... 🙄

Sleeπ Totgesagte leben länger!

AntwortZitat

Hallo!

Ich nutze in meinem Programm viele Subroutinen und würde Deine "Blinkroutine" entsprechend so ändern:

blinklinks    ldy yposm3
      lda #0
      sta (miss1),y
      mva hposp0 xposm3
      lda yposp1
      clc
      adc #6
      tay
      lda #48
      sta (miss1),y
      mva xposp1 p2pf
      mva xposp1 xposm3
      sty yposm3

      rts

blinkrechts   ldy yposm3
      lda #0
      sta (miss1),y
      lda yposp1
      clc
      adc #6
      tay
      lda #192
      sta (miss1),y
      lda xposp1
      clc
      adc #14
      sta p3pf
      mva xposp1 xposm3
      sty yposm3

      rts     

write   
      lda xposp1          ;Blinkabschnitt
      sta hposp0
      adc #2
      sta hposp3
      #if .byte blink<#64     ;Blink links
      jsr blinklinks
      #end
      #if .byte blink>#63 .and .byte blink<#128 ;Blink rechts
      jsr blinkrechts
      #end
      #if .byte blink>#127 .and .byte blink<#192  ;Blink links
      jsr blinklinks
      #end
      #if .byte blink>#191 .and .byte blink<#255  ;Blink rechts
      jsr blinkrechts
      #end

Bei mir funktioniert es.

Ist jetzt nur ein Beispiel, wie man den Code kürzen kann.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

... ich habe beide Änderungen eingebaut und noch den kleinen zusätzlichen Fehler beseitigt, der mich schon die ganze Zeit nervt - nämlich daß durch den Blinker immer mal wieder ein paar Bits auf dem Screen stehenbleiben - bei der Abfrage statt > und < einfach ein >= und <= ersetzt und schon ist es weg - logisch. Ansonsten finde ich die neue Blinkerroutine schlanker und strukturierter... supi. Auch den VBI auszulagern macht Sinn. Der VBI muss aber noch ein wenig schlanker werden, ein paar Sachen sollen da ja noch rein und die Sounds fehlen ja auch noch komplett. Außerdem muss ich den Aufbau der letzten Reihe noch optimieren..das hatte ich schon vorgestern deutlich besser und schlanker umgesetzt, aber nachts um 1:30 war dann mit meiner Konzentration Schluss und den einen Fehler habe ich einfach nicht wegbekommen und es wurde immer schlimmer, so daß ich auf meine alte Routine zurückgegangen bin und diese dann erweitert habe. Auch muss ich mir Gedanken machen, wie ich das so gestalte, daß ich die letzte Reihe einfacher konstruieren kann... so ist es ganz schön mühsam... vielleicht baue ich mit extra dafür ein kleines Programm welches übersichtlicher die Landschaft bauen läßt...

... gerade noch einen kleinen Bug in der Routine der letzten Reihe fixiert... da war ein inc var5 zu viel... jetzt läuft es ganz ohne Fehler 😎

AntwortZitat

Ich habe die komplette Joystickabfrage und Bewegung des Players ausserhalb des VBI. Als erstes wird der Joystick abgefragt, dann die neue Position berechnet. Nun warte ich auf einen VSync (also dass das Bild gerade nicht aufgebaut wird) und positioniere meinen Player.

; ############################################################################
; # VSync
; # 
    .proc WaitVSync

    lda VCOUNT
    cmp #$68
    bcc @+1

@   lda VCOUNT
    cmp #$68
    bcs @-

@   lda VCOUNT
    cmp #$68
    bcc @-

    rts

    .end

Die Routine schaut, welche Bildschirmzeile gerade aufgebaut wird. Ist der Wert kleiner $68 warte ich auf darauf, dass dieser Wert überschritten wird. Ist der Wert bereits über $68, warte ich erst einmal, dass dieser kleiner $68 ist.

Der Wert $68 kommt daher, dass mein Spielfeld nicht bis nach ganz unten reicht und ich somit mehr Zeit für die Playerdarstellung habe.

Vielleicht kannst Du das irgendwie nutzen?

Mein 600XL ist virenfrei!

AntwortZitat

Hallo Janko, das schaue ich mir mal später an.... das würde natürlich den VBI deutlich entlasten. Liebe Dank!!

AntwortZitat

Ich habe jetzt die anderen Items programmiert und dabei leider feststellen müssen, daß ich zu leichtfertig mit der Anzahl der Charakter umgegangen bin, denn plötzlich war b ei 128 Schluß... also ran ans Werk, optimieren und umprogrammieren. Danach ging es an die restlichen Items und danach habe ich die Landschaft weiter ausgebaut...
Nun werde ich die nächsten Tage und Wochen weiter an der Landschaft arbeiten, dann kommen noch Kollisionsabfragen und Aktionen auf die Kollisionen und weitere Items, die aktiv und animiert sind... danach Sound - ein noch riesiger Brocken! Das Projekt wächst und macht Spass...

Ein kleiner aktueller Stand anbei:rtp2.MOV

Anhänge:
AntwortZitat

... ich war trotz wenig Zeit nicht untätig! Bevor ich den Sound angehe, gibt es noch etliches an Code Bereinigung! Der VBI muss schlanker und ich habe zunächst mit dem Blinker des Raumschiffes begonnen. Für den Blinker hatte ich ursprünglich 2 Missiles benutzt und die im VBI aufwendig abwechselnd blinken lassen. Dadurch habe ich aber auch nur noch 2 Missiles für die Schüsse übrig. Ich habe das jetzt umprogrammiert und nehme zum blinken einfach einen weiteren Player, der am Raumschiff das Blinken übernimmt. Dadurch kann ich noch eine weitere Farbe ins Raumschiff bringen. Der ganze Code wird dadurch schon etwas schlanker. Anschließend habe ich fast den gesamten Blinkcode aus dem VBI ins Hauptprogramm gezogen und die ganzen zeitaufwendigen IF - Abfragen sind jetzt im Hauptcode. Jetzt kann ich den Code für die Schüsse umbauen - damit war ich noch nie so richtig zufrieden - außerdem sollen jetzt alle 4 Missiles als Schüsse benutzbar werden - auch den Code versuche ich wenn es geht auszulagern....
Liebe Grüße Peter

AntwortZitat

... die letzten Tage konnte ich endlich meinen Atari-Raum einrichten - noch ist es nicht fertig, aber ich habe schon mal meinen 130 XE aufgebaut, die Fujinet drangehängt, mit meinem Netzwerk verbunden und dann direkt mit meinem Mac das Programm retrun2phobos.xex gestartet... und es läuft. Das war der erste Test meines Programmes auf einem original Atari-Rechner. rtp2.1.jpgrtp2.2.jpg

Anhänge:
AntwortZitat

Sehr praktisch - programmieren auf dem Äpfelchen und testen direkt auf originaler Hardware ohne die Dateien erst hin-und herzukopieren. 😎

Sleeπ Totgesagte leben länger!

AntwortZitat

.... die letzten Tage habe ich wieder an der Explosion und speziell heute an den Schüssen rumgebastelt... Ziele sind folgende: 1. Die Explosion muss noch genauer werden - hier sind noch Fehler bei der genauen Erkennung der Position der Items und eigentlich sollen die Explosionen auch während des Scrolling fortwährend laufen und nicht direkt komplett, was ja immer einen kleinen Stopp bedeutet. 2. Ich habe das blinken umgebaut und überwiegend aus dem VBI rausgeholt - funktioniert ganz gut - und habe jetzt 4 Schüsse zur Verfügung. Diese sollen im Wechsel rechts und links laufen und auch durchaus gleichzeitig. Das ganze muss so gestaltet werden, daß auch hier der VBI entlastet wird, da ich ihn noch für Sound brauche.

zu 1: Das habe ich leider noch nicht hinbekommen. Die momentane Idee ist folgende: Ich brauche 12 Charakter für die Explosion und habe 4 Animationsphasen. Die lasse ich ständig laufen im Hintergrund und bei einem Treffer werden die 12 Charakter fürs Item mit den 12 Charaktern der Explosion überschrieben - das Scrolling geht dann automatisch weiter und ich muss mich nicht ums Timing kümmern. Da können dann auch mehrere Explosionen nebeneinander laufen - Problem ist dann nur der Start-/ und Endpunkt der Explosion.... dafür habe ich noch keine Lösung!

zu 2: Ich habe heute die Schüsse komplett umgebaut. Die Joystickabfrage (Strig0) und das Setzen der benötigten Parameter für den jeweiligen Schuss kann ich im Hauptprogramm machen - mache ich redundant im Feinscroll und an anderen Stellen. Aber die eigentliche Bewegung des Schusses geht quasi nur im VBI da sonst der Schuss viel zu langsam ist... und hier bekomme ich wieder ein Zeit- und Kapazitätsproblem im VBI. Ein Schuss kein Problem, 2 Schüsse geht auch noch ist aber tricky, 4 Schüsse unabhängig ... puh... da steigt mir der VBI aus. Da habe ich einfach zu viele Bedingungen und Abfragen.... das muss doch einfach und schlank gehen !!!!! Meine letzte Idee ist nun folgende: Alle 4 Schüsse laufen ständig unabhängig mit einer relativ schlanken Routine ständig im Hintergrund im VBI von oben nach unten durch - kommt dann der Impuls (durch Strig0) für einen Schuss, verändere ich einfach die x und y- Parameter für den jeweiligen Schuss und er wird sichtbar (x) und startet in Höhe Abschuss vom Raumschiff (y). Das will ich jetzt mal die Tage umsetzen...

Vielleicht hat ja jemand für beide Probleme auch die zündende und bessere Idee wie man es am besten macht, denn wenn ich mir die ganzen Spiele so anschaue, muss das doch eigentlich ganz easy sein! Grüße Peter

AntwortZitat

Hallo!

Ich habe so eine Routine für Missiles zwar noch nicht geschrieben, stelle es mir aber wie folgt vor:

missile .byte $00, $00, $00, $00  ; vier Schüsse
..
..
..
  .proc Schuessebewegen
  ldy $00
lp  ldx missile,y       ; Lade Y-Position Schuss 0-3
  cpx #$00          
  bne mv          ; Wenn ungleich 0 muss der Missile bewegt werden
nx  iny         ; Schussnr. hochzählen
  cpy #$04        ; max. 4 sind vorhanden
  bne lp          ; Wenn der letzte Schuss noch nicht bearbeitet, zurück
  rts         ; Unterroutine für Schüsse beendet

mv  tya         ; y retten
  pha         ; Unterroutine um den Schuss einen Schritt zu bewegen
      ..
      ..
      ..
  pla         ; y zurück holen
  tay
  jmp nx          ; nächsten Schuss bearbeiten
  .end

Wenn nun im Hauptprogramm festgestellt wird, dass geschossen wurde, bereitet man einen freien Missile vor, indem man ihn an die richtige Position setzt und setzt sta missile,x auf den y-Wert des Schusses. Die Routine erkennt nun dass der Missile bewegt werden muss. Man kann im Hauptprogramm die Kollision abfragen und dann auswerten."missile" sollte auf 0 gesetzt werden, wenn der Schuss den untern Rand erreicht hat oder ein Treffer erfolgte.

Ich hoffe Du kannst meinen Gedanken folgen und es hilft Dir weiter.

Janko

Mein 600XL ist virenfrei!

AntwortZitat

Hallo Janko und vielen Dank für deinen kreativen Lösungsansatz! So ähnlich wie du es schreibst, habe ich es auch jetzt vor! Allerdings möchte ich so wenig Abfragen und Bedingungen in die Missileroutine im VBI reinpacken wie möglich. Rein theoretisch sollte es ja zu 4 Schüssen gleichzeitig kommen können, daher muss der VBI das auch zeitlich abarbeiten können - sonst macht es keinen Sinn. Dann kann das aber auch ständig im Hintergrund laufen und ich mache es nur jeweils (durch x-Positionierung) sichtbar. Also alle 4 Missiles laufen ständig vom Bildschirmoberrand zum Unterrand - wenn der Unterrand erreicht wird, dann startet der Missile wieder von oben. Die X-Position wird auf 0 gesetzt - also sieht man die Missiles primär nicht. Die Joystickabfrage läuft im Hauptprogramm (das packe ich in die Feinscrollroutine, da ich hier noch Zeit habe und eh mit einer Warteschleife verzögern muss) - sobald der Feuerknopf gedrückt wurde kommt der entsprechende Werte in die y-Position und x-Position des jeweiligen Missile und er wird sichtbar. Läuft er nach ganz unten oder an den Boarderrand geht x auf Null und der Missile wird wieder unsichtbar - passiert eine Kollision mit einem Item startet die Explosionsroutine. Entsprechend läuft das mit den anderen drei Missiles....

AntwortZitat

... hier nun das erste Ergebnis:

Ich habe zunächst ein Missile umgesetzt. Die Routine im VBI sieht. nun extrem abgespeckt so aus:

rtp2bild.jpg

Alles andere läuft im Hauptprogramm. Die Joystickabfrage für den Schuss und das Setzen der Parameter. Ich habe den Schuss zur Kontrolle noch sichtbar am linken Bildrand mitlaufen lassen und man sieht im Video sehr schön, daß der Schuss ständig läuft und wegen des schlanken Codes den VBI praktisch gar nicht belastet. Drückt man den Feuerknopf, wird die Position auf x und y verändert und der Schuss wird sichtbar bis der untere Rand erreicht ist - dann geht die x Position wieder auf den hier noch gerade sichtbaren Bereich am linken Rand. Beim finalen Spiel wandert der dann natürlich ganz raus. Es sind noch ein paar Fehler drin und die Kollisionsabfrage muss noch rein! Außerdem muss noch eine intelligente Steuerung der 4 Schüsse rein, die einmal abgefeuert ja bis nach unten oder bis zur Kollision durchlaufen müssen. Hier das kurze Video:#

rtp2video.MOV

Peter

Anhänge:
AntwortZitat

Heute habe ich an den Schüssen gearbeitet und alle 4 Schüsse funktionieren jetzt gut. Der Hauptcode liegt im Hauptprogramm und der VBI ist schlank und wenig belastet. Leider habe ich schon das nächste massive Problem... Aber hier erstmal der Code vom VBI und vom Hauptprogramm:

;@com.wudsn.ide.asm.mainsourcefile=r2phobos.asm


                ;vertical blank interrupt fr Joystick / PM

  .proc vbinter     
      pha
      txa
      pha
      tya
      pha
      mva #0 atract   ;Bildschirmschoner aus

      clc         ;Kollisionen abfragen
      lda p0pf
      cmp #1
      bcc @+
      mva #1 kollp0
@     
      clc         ;Joystickabfragen Player1
      lda stick0
      cmp #15       ;keine Joystickaktion
      bcs @+
      cmp #14
      bcs nachob
      cmp #13
      bcs nachun
      cmp #11
      bcs nachli
      cmp #10
      bcs nachliob
      cmp #9
      bcs nachliun
      sec
      cmp #7
      bcs nachre
      cmp #6
      bcs nachreob
      cmp #5
      bcs nachreun
@     jmp write
nachre    clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp write
nachreun
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachun
nachreob
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
@     jmp nachob
nachli    sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp write
nachliun
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachun
nachliob
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
@     jmp nachob
nachob
      dec yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
nachun
      inc yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
      clc
write   sec
      lda xposp1          ;x-Position der Player setzen
      sta hposp0
      sbc #0
      sta hposp2
      adc #2
      sta hposp3

      ldy yposp1          ;Player printen
      clc
      lda blink
      tax
      dey
      mva #0 lms2           
@     lda pm41,x
      sta (play4),y
      lda pm42,x
      sta (play3),y
      iny
      inx
      inc lms2
      lda lms2
      cmp #14
      bne @-
                    ;Schüsse laufen ständig 

      jsr schuesse
      mva m0pf kollm1
      mva m1pf kollm2
      mva m2pf kollm3
      mva m3pf kollm4
      mva #1 hitclr

      ;-------------------------------------------------------------


      pla
      tay
      pla
      tax
      pla
      jmp xitvbv      ;vb-interrupt wird über xitvbv beendet!!





  .endp
      org $2000

      icl '../hardware.txt'
      icl 'header.txt'
      icl 'character.asm'
      icl 'lands.asm' 

  .proc dlist
        .by 112,112,112,100
      .by 30,75
:21     .by 36
:5      .by 4
      .by 65
      .wo dlist
  .endp


      icl 'pmg_vars.asm'

      .proc main

main1   mwa #dlist 560  
      mva #10 yposp1
      mva #120 xposp1
      mva #42 yposm1
      mva #0 xposm1
      mva #94 yposm2
      mva #49 xposm2
      mva #0 tank1x
      mva #0 tank1y
      mva #151 fuelzaehleritem
      mva #0 fuelzaehler
      jsr text

Start1    mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
      mva #192 gprior ;GTIA Modus 3 
      mva #12 color3  ;Schriftfarbe 
      mva #220 color1 ;Gelb
      mva #153 color0 ;Blau
      ;mva #52 color0 ;Rot
      mva #180 color2 ; Grün
      mva #0 color4 ;Hintergrundfarbe
      lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1 \ sta feuer6

      ; Player vorbereiten und initialisieren
      ; Kollisionen:  4 = Grün   2 = Gelb
      lda ramtop
      sec
      sbc #16
      sta pmbase
      clc
      adc #3
      sta miss1+1           
      sta miss2+1
      sta miss3+1
      sta miss4+1
      adc #1
      sta play1+1
      adc #2
      sta play3+1
      adc #1
      sta play4+1
      lda #9
      sta play4
      lda #3
      sta play3

      mva #62 sdmctl
      mva #56 pcolr0
      mva #15 pcolr1
      mva #119 pcolr2
      mva #191 pcolr3
      mva #1 gprior
      mva #3 gractl
      mva #1 sizep0
      mva #1 sizep1
      mva #1 sizep2
      mva #0 sizem
      mva #0 rechts
      mva #2 hitclr
      mva #48 blink
      mva #40 p1pf
      mva #8 hposm0
      mva #8 hposm1
      mva #8 hposm2
      mva #8 hposm3
      mva #1 yschuss1
      mva #11 yschuss2
      mva #22 yschuss3
      mva #33 yschuss4
      mva #1 schussi

main2   mva <lands var6
      mva >lands var6+1
      mva #0 kollp0
      ldy #255        ;Speicher Player 1 leeren
      lda #0
      sta play1
@     sta (play1),y
      sta (play4),y
      sta (play3),y
      dey
      bpl @-
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      clc
      ldy #0
      ldx #0


      ldx #>vbinter     ;VB-Interrupt VektorHi
      ldy #<vbinter     ;VB-Interrupt VektorLo
      lda #7          ;Deferred Mode mit lda #7 festlegen
      jsr setvbv        ;Vektor für die eigene Routine über setvbv eintragen


hauptprogramm




      #if .byte yschuss1>#207 .or .byte kollm1=#4
      ldy yschuss1
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm0
      mva #1 hitclr
      #end
      #if .byte yschuss2>#207 .or .byte kollm2=#4
      ldy yschuss2
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm1
      mva #1 hitclr
      #end
      #if .byte yschuss3>#207 .or .byte kollm3=#4
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm2
      mva #1 hitclr
      #end
      #if .byte yschuss4>#207 .or .byte kollm4=#4
      ldy yschuss4
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #1 hitclr
      mva #8 hposm3
      #end

      lda blink2
      adc #59
      sta blink2
      #if .byte blink2>=#0 .and .byte blink2<#60
      mva #0 blink
      #end
      #if .byte blink2>=#60 .and .byte blink2<#120
      mva #14 blink
      #end
      #if .byte blink2>=#120 .and .byte blink2<=#180
      mva #28 blink
      #end
      #if .byte blink2>=#180 .and .byte blink2<=#255
      mva #42 blink
      #end
      clc
      lda kollp0
      cmp #1
      bcc @+

      mva #0 kollp0
@     
      jsr letztereihe     ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)  
      jsr feinscroll      ;Feinscroll Bildschirm1 ausführen (sichtbar)    

      mva #$30 var1     ;var1 auf 30000 ($7530) setzen
      mva #$75 var1+1
      mva #$E4 var2     ;var2 auf 31460 ($7AE4) setzen
      mva #$7A var2+1
      jsr grobscroll      ;Bildschirm1 kopieren + grobscroll
      mva #$0C var1     ;var1 + var2 auf 31500 ($7B0C) setzen
      mva #$0C var2
      mva #$7B var1+1
      mva #$7B var2+1 

      jsr schusslogik
      jsr umschalten

      inc fuelzaehleritem
      lda fuelzaehler
      tax
      lda fuelzaehleritem
      sta 31043,x
      sta 32543,x
      #if .byte fuelzaehleritem=#155
      mva #151 fuelzaehleritem
      inc fuelzaehler
      #end
      #if .byte fuelzaehler>#200
      mva #0 fuelzaehler
      #end
      #if .byte fuelzaehler=#20
      mva #52 color3
      #end
      #if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
      ;jmp main1
      mva #0 fuelzaehler        ;Fuel zuende Neustart
      #end

      jsr letztereihe     
      jsr feinscroll      ;Feinscroll Bildschirm2 ausführen (sichtbar)            
      mva #$08 var2     ;var1 auf 29960 ($7508) setzen
      mva #$75 var2+1
      mva #$0C var1     ;var2 auf 31500 ($7B0C) setzen
      mva #$7B var1+1

      #if .byte kollges=#4
      mva #15 color3
      sec
      lda fuelzaehler
      sbc #10
      sta fuelzaehler 
      tax
      mva #151 fuelzaehleritem
      clc
      lda fuelzaehleritem
@     sta 31043,x
      sta 32543,x
      inx
      cpx #36
      bne @-
      jsr kollitem
      mva #0 kollm1
      #end

      mva #$08 var2     ;var1 auf 29960 ($7508) setzen
      mva #$75 var2+1
      mva #$0C var1     ;var2 auf 31500 ($7B0C) setzen
      mva #$7B var1+1
      jsr grobscroll      ;;Bildschirm2 kopieren + grobscroll
      mva #$30 var1     ;var1 + var2 auf 30000 ($7530) setzen
      mva #$30 var2
      mva #$75 var1+1
      mva #$75 var2+1

      jsr schusslogik
      jsr umschalten      ;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar

      inc fuelzaehleritem
      lda fuelzaehler
      tax
      lda fuelzaehleritem
      sta 31043,x
      sta 32543,x
      #if .byte fuelzaehleritem=#155
      mva #151 fuelzaehleritem
      inc fuelzaehler
      #end

      ;Ende der Bildschirmausführung / Kontrolle Durchläufe
      sec
      lda #45   ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
      sbc var6+1
      bpl @+
      jmp start1      ;Stop hier
@   
      jmp hauptprogramm       ;weiter

      .endp

      ; _____________________________________________________________________________________
      ;
      ; ---------------------------- S U B R O U T I N E N ----------------------------------
      ; _____________________________________________________________________________________


      icl 'VBI.asm'
      ; -------------------------------------------------------------------------------------

  .proc kollision
      ldx #0
      clc
@     inx
      cpx #255
      bcc @-
      rts
  .endp
      ; -------------------------------------------------------------------------------------

  .proc umschalten
      ldy #4        ;Bildschirme umschalten von unsichtbar auf sichtbar 
      mva sdlstl var5
      mva sdlstl+1 var5+1
      lda var1
      sta (var5),y
      iny
      lda var1+1
      sta (var5),y
      rts
  .endp
      ; -------------------------------------------------------------------------------------

  .proc wartes
      clc
        ldx delay ; Warteschleife
st      lda RTCLOK+2    
wa      cmp RTCLOK+2    
          beq wa    
          dex            
          bpl st 
          rts
        .endp


    .proc warte2

      clc
@     dec delay1
      lda delay1
      cmp #1
      bne @-


        rts

      .endp

          ; -------------------------------------------------------------------------------------

  .proc feinscroll
      ldy #1
      mva #0 delay
      mva #255 delay1
@     jsr wartes

      sty vscrol
      iny
      cpy #8
      bne @-  


      rts
        .endp 
          ; --------------------------------------------------------------------------------------

   .proc schusslogik


        #if .byte strig0=#0 
        asl schussi
      #end

      #if .byte schussi=#2
      lda xposp1 
      sta hposm0
      lda #0
      ldy yschuss1
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss1
      asl schussi
      #end

      #if .byte schussi=#8
      lda xposp1 
      adc #12
      sta hposm1
      lda #0
      ldy yschuss2
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss2
      asl schussi
      #end

      #if .byte schussi=#32
      lda xposp1 
      sta hposm2
      lda #0
      ldy yschuss3
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss3
      asl schussi
      #end

      #if .byte schussi=#128
      lda xposp1
      adc #12 
      sta hposm3
      lda #0
      ldy yschuss4
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss4
      mva #1 schussi
      #end

        rts

      .endp

         ; --------------------------------------------------------------------------------------   
  .proc grobscroll  
      ;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile

      ldx #22
@     ldy #$28
      clc
@     lda (var1),y 
      sta itemex
      #if .byte itemex=#68
      jsr fuel
      #end
      sta (var2),y
      dey
      bpl @-
      clc
      lda var1
      adc #$28
      sta var1
      bcc @+
      inc var1+1
@     clc
      lda var2
      adc #$28
      sta var2
      bcc @+
      inc var2+1      
@     clc
      dex
      bpl @-3

      rts
  .endp   
      ; -------------------------------------------------------------------------------

  .proc letztereihe
      ;Die letzte Reihe printen 
      ;Start der letzten Reihe bei var1 - Line 22
      ;in Var6 (+1) wird die Position von lands gespeichert
      ;in Var5 gehen Infos der Boarderanzahl rein
      ;in y ist der Zähler für letzte Reihe
      ;x wird als Zähler fürs printen benutzt

      lda var1+1
      ;sta var8+1
      ;sta var7+1
      lda var1
      ;sta var8
      ;sta var7
      adc #112
      sta var1
      inc var1+1
      inc var1+1
      inc var1+1
      ldy #0
      clc
      lda (var6),y  ;Boarderanzahl 1 holen
      sta var5
      tax       ;Boarderanzahl 1 in x speichern
      jsr var6up
      lda (var6),y  ;Boarderart 1 holen
      sta var7    ;abspeichern in var7
@     iny
      sta (var1),y  ;Boarder1 printen
      dex
      bpl @-  
      jsr var6up
      lda (var6),y  ;Boarderanzahl 2 holen
      tax
      jsr var6up
      lda (var6),y  ;Boarderart 2 holen
      ldy var5
@     iny      
      sta (var1),y  ;printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda (var6),y  ;Rand Boarder2 holen
      inc var5    ;Zeilenzähler eins weiter
      ldy var5  
      sta (var1),y  ;Rand Boarder1 printen
      jsr var6up
      lda(var6),y   ;leer holen
      tax
      lda #0
      ldy var5      
@     iny      
      sta (var1),y  ;leer printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Rand Boarder3 holen
      ldy var5
      iny
      sty var5
      sta (var1),y  ;Rand Boarder3 printen
      jsr var6up
      lda(var6),y   ;Boarder4 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder4 printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Boarder5 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder5 printen
      dex
      bpl @-
      jsr var6up
      lda (var6),y  ;Sonderitem holen
      sta var5    ;Item in Var5 speichern
      #if .byte var5=#99
      jmp *
      #end
      jsr var6up
      #if .byte var5=#50  ;Öltank printen
      ldx #11
      clc
@     mva tankol,x pr1,x
      dex
      bpl @-
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Fueltank printen
      #end

      #if .byte var5=#51  ;Rakete printen
      ldx #11
      clc
@     mva rakete,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Rakete printen
      #end

      #if .byte var5=#52  ;Alien printen
      ldx #11
      clc
@     mva alien,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Alien printen
      #end
      #if .byte var5=#53  ;TNT printen
      ldx #11
      clc
@     mva tnt,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;TNT printen
      #end
      jsr var6up
      mva #0 vscrol
      sec
      lda tank1y
      sbc #40
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      lda tank1x
      tay
      mva #0 var5

      rts

var6up    clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1

      rts
  .endp
      ; --------------------------------------------------------------------------------------

  .proc fuel
      sec       ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
      lda var1
      sbc #160
      sta var2
      lda var1+1
      sbc #0
      sta var2+1
fuelex    lda pr1
      sta (var2),y  ;1

      lda pr2
      iny
      sta (var2),y  ;2

      lda pr3
      iny
      sta (var2),y  ;3
      clc
      lda var2
      adc #41
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dey

      lda pr4
      sta (var2),y  ;4
      dey

      lda pr5
      sta (var2),y  ;5
      dey

      lda pr6
      sta (var2),y  ;6
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1

      lda pr7
      sta (var2),y  ;7

      lda pr8
      iny
      sta (var2),y  ;8

      lda pr9
      iny
      sta (var2),y  ;9 
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1

      lda pr10
      sta (var2),y  ;10
      dey

      lda pr11
      sta (var2),y  ;11
      dey

      lda pr12
      sta (var2),y  ;12
      tya
      rts
  .endp
      ; ------------------------------------------------------------------------------


  .proc kollitem          ;Kollisionsroutine
              ;var8 unveränderter Bildschirmanfang      
      lda yschuss1  ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
      sec
      sbc #32
      clc
      ror
      clc
      ror
      clc
      ror
      sta yschuss1  ;y-Position in das x-Register schreiben
      tax 
      dex       ; und einen abziehen
      lda xschuss1  ;x-Position -48 (sichtbarer Bereich)und /4
      sec
      sbc #48
      clc
      ror
      clc
      ror
      tay       ;in y geht die x-Position
      sec
      mva var1 var2   ;holen der Bildschirmadresse -> var2
      mva var1+1 var2+1
      clc
@     lda var2    ;jetzt die y-Position auf die richtige Höhe stellen
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dex
      bpl @-      ;die y-Position steht in x - Addition von x Zeilen
@     dey       ;die korrekte x-Position einstellen
      lda (var2),y  ;linken Rand checken
      sta var8    
      iny
      iny
      lda (var2),y  ;rechten Rand checken
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0  ;Position nach rechts anpassen 
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0  ;Position nach links anpassen
      dey
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      iny
      iny
      lda (var2),y
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0
      dey
      #end
      lda (var2),y    ;Korrektur der y-Position
      sta var8      ;in var8 aktuelle BS-Position
      sec
      lda var2      ;eins drüber - bleibt wenn var2 zu tief
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y    ;lade Bildschirminhalt eins drüber
      sta var9      ;das geht in var9 rein
      #if .byte var8>#0 .and .byte var9=#0  ;alte Position var2 
      clc                   ;wiederherstellen
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0  ;alte Position var2
      clc                   ;eins runter
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      sec
      lda var2
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y
      sta var9
      #if .byte var8>#0 .and .byte var9=#0
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0
      clc
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
                ;ab hier stimmt die Position des Items (meistens)
                ;in der Variable y für x-Position
                ;und in var2 für die y-Position 
expl11    
      mva var2 tank1pos   ;y-Position für Explosion1
      mva var2+1 tank1pos+1
      ldx #11
      clc
@     mva expl1,x pr1,x
      dex
      bpl @-  
      jsr fuel.fuelex
      tay
      iny
expl22    
      mva #80 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      ldx #11
      clc
@     mva expl2,x pr1,x
      dex
      bpl @-  
      jsr fuel.fuelex
      tay
      iny

expl33    
      mva #92 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      ldx #11
      clc
@     mva expl3,x pr1,x
      dex
      bpl @-  
      jsr fuel.fuelex
      tay
      iny
expl44    
      mva #104 var5
      mva tank1pos var2
      mva tank1pos+1 var2+1
      mva #1 delay
      jsr wartes
      ldx #11
      clc
@     mva expl4,x pr1,x
      dex
      bpl @-  
      jsr fuel.fuelex
      tay
      iny
      rts
  .endp
      ; ------------------------------------------------------------------------------
  .proc schuesse

      ldy yschuss1
      iny
      iny
      lda #1
      sta (miss1),Y
      sty yschuss1
      lda #0
      dey
      dey
      sta (miss1),Y
      mva m0pf kollm1

      ldy yschuss2
      iny
      iny
      lda #4
      sta (miss1),Y
      sty yschuss2
      lda #0
      dey
      dey
      sta (miss1),Y
      mva m1pf kollm2

      ldy yschuss3
      iny
      iny
      lda #16
      sta (miss1),Y
      sty yschuss3
      lda #0
      dey
      dey
      sta (miss1),Y
      mva m2pf kollm3

      ldy yschuss4
      iny
      iny
      lda #64
      sta (miss1),Y
      sty yschuss4
      lda #0
      dey
      dey
      sta (miss1),Y
      mva m3pf kollm4
      rts



  .endp

  .proc text
      ldx #0
      lda #52
      jsr prte
      inx
      lda #45
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #31
      jsr prte
      inx
      lda #52
      jsr prte
      inx
      lda #49
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #51
      jsr prte
      inx
      lda #47
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #42
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #53
      jsr prte
      inx
      lda #0
      jsr prte 
      inx
      lda #55
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #32
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #54
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #50
      jsr prte 
      inx
      lda #44
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #47
      jsr prte 
      inx
      lda #48
      jsr prte 
      inx 
      lda #0
      jsr prte      

      ldx #0    ;Fuel
      lda #46
      jsr prte2
      inx
      lda #31
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #48
      jsr prte2

      ldx #10   ;Score
      lda #53
      jsr prte2
      inx
      lda #43
      jsr prte2
      inx
      lda #50
      jsr prte2
      inx
      lda #52
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #0
      jsr prte2
      inx
      lda #160
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      ldx #23   ;Ships
      lda #53
      jsr prte2
      inx
      lda #47
      jsr prte2
      inx
      lda #33
      jsr prte2
      inx
      lda #51
      jsr prte2
      inx
      lda #53
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      ldx #0
fuellauf  
      clc
      lda fuelzaehleritem
@     jsr prte3
      inx
      cpx #36
      bne @-
      rts
prte    sta 30923,x
      sta 32423,x
      rts
prte2   sta 31003,x
      sta 32503,x
      rts
prte3   sta 31043,x
      sta 32543,x
      rts
  .endp
      ; ------------------------------------------------------------------------------


      run main

und noch ein kleines Video: rtp2.MOV

Anhänge:
AntwortZitat

und nun das Problem:

Es sind die Kollisionen... Die Missiles laufen ja im VBI und erkennen dort auch die Kollisionen. Wenn jetzt im Hauptprogramm die Abfragen kommen und die verschiedenen Aktionen der jeweiligen Kollision, ist der Missile ja bevor überhaupt was passiert im VBI schon ein paar Zeilen weitergegangen und hat dann schon ganz andere Kollisionen gemacht bzw. die eigentliche Aktion kommt im Hauptprogramm zu spät.... ich habe heute einige Stunden mit allen möglichen Varianten experimentiert aber keine gute Lösung gefunden. Programmiere ich die ganze Schusslogik im Hauptprogramm, laufen die Missiles zu langsam und ruckeln. Programmiere ich alles im VBI dann verbrauche ich dort wieder zu viel Zeit. Ich fürchte aber es geht nicht anders... Oder übersehe ich da etwas?? LG Peter

AntwortZitat

Hi!

Evtl. geht ja ein Gemisch? Im VBI wird die Kollision erkannt und der Missile ausgeblendet. Du setzt eine Variable Kollision auf true und merkst Dir die Position der Kollision. Im Hauptprogramm erkennst Du nun die Kollision und die Position und kümmerst Dich um die weitere Logik.

Wenn die Animation der Kollision minimal verzögert kommt, sollte das kein Problem sein. Der Schuss ist weg und somit optisch kollidiert.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Hallo Janko, wo kommst du nochmal her?? Vielleicht sollten wir mal ein Projekt zusammen machen, ich glaube wir ticken ganz ähnlich. Ich habe mir natürlich auch nebenher Gedanken gemacht, wie ich das lösen kann und bin auf den gleichen Ansatz gekommen.

Die Schüsse müssen gut laufen und die Kollisionen müssen stabil klappen, sonst geht ja der Spielspass flöten. Also habe ich mir jetzt gesagt: VBI erstmal egal, ich muss da noch mehr Code reinpacken. Das habe ich jetzt auch umgesetzt und es jetzt so zunächst gelöst: Die Missiles laufen ja ständig im VBI unsichtbar und ich biege nur die x- und y-Position jeweils um, wenn der Feuerknopf gedrückt wird. Für die Abfolge der Schüsse nehme ich eine Extravariable, da steht eine 1 drin, die mit dem Befehl ASL bitweise verschoben wird. Das steuert die Schüsse in der Folge rechts links rechts links. Diese Schusslogik findet im Hauptprogramm statt. Damit die Schüsse schneller laufen, incrementiere ich sie im VBI 2x - das Problem dabei ist, daß dann 2 verschiedene Kollisionen stattfinden können. Eine gewollte und eine ungewollte. Dafür halte ich 4x2 Variablen bereit und packe die jeweilige Kollisionsart in diese Variable rein - für alle 4 Schüsse. Das läuft auch ständig im VBI. Sobald eine Kollision eines Missiles stattfindet, biege ich den x-Vektor dieses Missiles im VBI weg, damit dann keine weiteren Kollisionen stattfinden können und die ersten Ereignisse überschreiben können. Dieser Aufwand muss wohl im VBI sein, vielleicht kann ich den Code noch etwas optimieren. Alles andere muss dann im Hauptprogramm erfolgen. Wahrscheinlich muss ich im VBI auch noch die jeweiligen x und y-Positionen retten!

Das System ist zunehmend sensibel finde ich. Nach diesen Änderungen bekomme ich ab und zu ein unangenehmes Ruckeln rein - mal ja und mal nicht. Habe noch nicht rausgefunden woher das kommt.... ich dachte erst an der Lände des VBI, aber wenn ich den Emulator auf 60 Hz umstelle, läuft es stabiler - dann kann es ja nicht an der Codelänge im VBI liegen.

Ganz schön kompliziert so ein Shooter....... ich glaube als nächstes Projekt mache ich mal ein feines Jump ´n Run - Spiel 😉 Gruß Peter

AntwortZitat
              ;Schüsse 1-4 laufen incl. Kollisionsabfragen
      lda #1      
      ldy yschuss1
      iny
      sta (miss1),Y
      mva m0pf kollm1
      lda #1
      iny
      sta (miss1),y
      mva m0pf kollm12
      sty yschuss1
      lda #0
      dey
      dey
      sta (miss1),Y
      iny
      sta (miss1),y

      lda #4      
      ldy yschuss2
      iny
      sta (miss1),Y
      mva m1pf kollm2
      lda #4
      iny
      sta (miss1),y
      mva m1pf kollm22
      sty yschuss2
      lda #0
      dey
      dey
      sta (miss1),Y
      iny
      sta (miss1),y

      lda #16     
      ldy yschuss3
      iny
      sta (miss1),Y
      mva m2pf kollm3
      lda #16
      iny
      sta (miss1),y
      mva m2pf kollm32
      sty yschuss3
      lda #0
      dey
      dey
      sta (miss1),Y
      iny
      sta (miss1),y

      lda #64 
      ldy yschuss4
      iny
      sta (miss1),Y
      mva m3pf kollm4
      lda #64
      iny
      sta (miss1),y
      mva m3pf kollm42
      sty yschuss4
      lda #0
      dey
      dey
      sta (miss1),Y
      iny
      sta (miss1),y

      mva #1 hitclr
AntwortZitat

Ich habe jetzt mal rumexperimentiert, aber dieses Bildschirmruckeln ist blöd, da es auch dann ab und zu Fehler in der Landschaft produziert. Ich kann es auch kaum reproduzieren... manchmal ruckelt es stark und manchmal gar nicht.

Heute habe ich dann auf 2 Schüsse verzichtet und somit den Code im VBI deutlich reduziert - das Ruckeln ist weg. Auch habe ich die komplizierten If Then Or Schleifen weggelassen und es nativ programmiert - in der Hoffnung, daß es stabiler läuft. Fazit: Weniger Code im VBI stabilisiert das System, aber auch mit 2 Schüssen scheine ich nicht viel Luft zu haben, was seltsam anmutet... habe ich mich verrechnet? Ich war von ca. 1500 Befehlen - also 7000-8000 Taktzyklen ausgegangen. Mit 4 Schüssen verbrauche ich 610 Befehle, mit 2S Schüssen nur 380 Befehle - also noch viel Luft nach oben. Woran hängt es dann? Schafft der Rechner zwar die 610 Befehle ohne dass er abstürzt aber mit zunehmender Belastung des VBI wird das System instabil??? So bekomme ich keinen vernünftigen Sound mehr rein... Oder habe ich irgendwo einen Denkfehler?? Muss ich ganz gezielt WSYNC einsetzen (alle Versuche machte es eher schlechter). Ist meine Lösung mit dem Fein-/Grobscroll mit 2 Bildschirmen zu instabil??? Wie bloß haben die Jungs das früher programmiert und die Shooter so schön hinbekommen?? Für Ideen bin ich echt dankbar! Gruß Peter

AntwortZitat

Hallo Peter,

hier mal ein theoretischer Ansatz, ohne Gewähr auf Richtigkeit 😉

Der ATARI läuft zwar mit ca. 1,79Mhz, aber den größten Teil ist die CPU blockiert, damit die Grafik dargestellt werden kann. Die meiste "freie" Zeit hat der ATARI wenn das Bild gerade fertig aufgebaut wurde und ein neuer Aufbau vorbereitet wird. Das ist dann auch die Zeit des VBI. Also je mehr Code im VBI ausgeführt wird, desto weniger kann der ATARI außerhalb des VBI bearbeiten.

Der VBI wird alle 1/50 Sekunde aufgerufen. Das heißt alles im VBI wird alle 20ms erneut ausgeführt.

Die Frage ist somit, muss wirklich alles immer 50x die Sekunde abgearbeitet werden? Kann man vllt. Code aufteilen, so dass im 1. VBI Teil A, im 2. VBI Teil B und im 3. VBI Teil C bearbeitet wird, und dann wieder von vorne? Nur wichtiger Code wird jedes Mal ausgeführt.

Beispiel Scrolling im VBI: 1. VBI - Feinscolling +1 im sichtbaren Bereich und 256 Byte im ausgeblendeten wird verschoben. 2. VBI - Feinscolling +1 im sichtbaren Bereich und weitere 256 Byte im ausgeblendeten wird verschoben. 3. VBI - Feinscolling +1 im sichtbaren Bereich und weitere 256 Byte im ausgeblendeten wird verschoben. 4. VBI - Feinscolling +1 im sichtbaren Bereich und die letzen 256 Byte im ausgeblendeten wird verschoben. 5. VBI - Feinscolling +1 die letzte Zeile wird aus den Daten erzeugt 6. VBI - Feinscolling +1 Objekte werden entfernt, die bereits abgeschossen wurden 7. VBI - Feinscolling +1 Punktestand und Fuel etc. werden ausgegeben/aktualisiert 8. VBI - Feinscolling wieder zurücksetzen und umblenden

Hoffentlich habe ich jetzt nicht zu viel Mist erzählt und Du kannst damit etwas anfangen 🙂

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Hi Janko, erst einmal vielen Dank für den wirklich kreativen Ansatz. Ich dachte wirklich in dem Moment, als ich es gelesen hatte: Das ist es. Und habe es gerade mal mit einfacher Teilung des VBI umgesetzt... so einfach geht es leider nicht. Es ruckelt mindestens genauso und die Steuerung und die Missiles laufen abgehackt. Vielleicht kann man das noch besser umsetzten, wird aber richtig kompliziert... der VBI, gesteuert durch das Hauptprogramm geht nicht gut, aber.... er läßt sich steuern und aufrufen durch den DLI und dann kann ich den VBI in Portionen teilen und jeweils aufrufen.

Und dann fiel mir noch folgendes ein: Warum nicht einfach den VBI2 durch den VBI1 aufrufen und dann VBI3 durch VBI2 usw..... das habe ich gerade mal umgesetzt und einen schönen Systemabsturz erwartet... aber siehe da: Es funktioniert. Und läuft flüssig und mit 4 Schüssen ganz ohne ruckeln!! Wie cool !! Ok, die Steuerung ist natürlich etwas träger und die Missiles laufen etwas langsamer runter - das muss ich noch anpassen. Aber zumindest ist das wohl die Lösung der Probleme. Hurra!!!!! Gruß Peter

... Danke für die notwendige Inspiration!!

AntwortZitat

... heute habe ich eine Menge experimentiert mit den VBI´s.... folgendes kann ich nun berichten:

Zeit bleibt Zeit und das kann man nicht ändern. Teile ich den langen VBI in 2 VBI´s, dann läuft das System stabil und rund, aber man merkt die Einbuße der Geschwindigkeit. Die Joysticksteuerung wird etwas träger und ich muss die x- und y-Verschiebung des Raumschiffes anpassen (Werte verdoppeln). Dadurch läuft es noch gut aber nicht mehr ganz so flüssig. Gleiches gilt für die Missiles... auch hier musste ich die Geschwindigkeit verdoppeln, da sonst die Missiles zu langsam runterlaufen. Ich kann noch weitere VBI´s einbauen und so weiter "teilen" - Thema Musik, das wird alles andere aber logischerweise weiter verlangsamen... hier gibt es also ganz klar Grenzen!! Ich lass das jetzt erst einmal so und mache weiter. Am Ende schaue ich, daß ich noch ein wenig Code vom VBI ins Hauptprogramm packe... vielleicht experimentiere ich auch noch mit dem DLI - aber der ist ja noch zeitkritischer.

Immerhin kann man eines sagen: Einen VBI durch einen anderen VBI aufzurufen geht einfach und gut, man kann da direkt den Vektor umbiegen und muss nicht erst durch setvbv durchspringen... anbei das vorläufige Listing des VBI:

.proc vbinter     
      pha
      txa
      pha
      tya
      pha
      mva #0 atract   ;Bildschirmschoner aus

      clc         ;Kollisionen abfragen
      lda p0pf
      cmp #1
      bcc @+
      mva #1 kollp0
@     
      clc         ;Joystickabfragen Player1
      lda stick0
      cmp #15       ;keine Joystickaktion
      bcs @+
      cmp #14
      bcs nachob
      cmp #13
      bcs nachun1
      cmp #11
      bcs nachli
      cmp #10
      bcs nachliob
      cmp #9
      bcs nachliun
      sec
      cmp #7
      bcs nachre
      cmp #6
      bcs nachreob
      cmp #5
      bcs nachreun
@     jmp write
nachun1   jmp nachun
nachre    clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
      inc xposp1
@     jmp write
nachreun
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
      inc xposp1
@     jmp nachun
nachreob
      clc
      lda xposp1
      cmp #192
      bcs @+
      inc xposp1
      inc xposp1
@     jmp nachob
nachli    sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
      dec xposp1
@     jmp write
nachliun
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
      dec xposp1
@     jmp nachun
nachliob
      sec
      lda xposp1
      cmp #49
      bcc @+
      dec xposp1
      dec xposp1
@     jmp nachob
nachob

      dec yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
nachun

      inc yposp1
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-
      jmp write
      clc
write   sec
      lda xposp1          ;x-Position der Player setzen
      sta hposp0
      sbc #0
      sta hposp2
      adc #2
      sta hposp3

      ldy yposp1          ;Player printen
      clc
      lda blink
      tax
      dey
      mva #0 lms2           
@     lda pm41,x
      sta (play4),y
      lda pm42,x
      sta (play3),y
      iny
      inx
      inc lms2
      lda lms2
      cmp #14
      bne @-

      mwa #vbinter2 $224

      pla
      tay
      pla
      tax
      pla

      jmp xitvbv      ;vb-interrupt wird über xitvbv beendet!!





  .endp

  .proc vbinter2      

      pha
      txa
      pha
      tya
      pha
                  ;Schüsse 1-4 laufen incl. Kollisionsabfragen
      lda #1      
      ldy yschuss1
      iny
      iny
      sta (miss1),Y
      mva m0pf kollm1
      lda #1
      iny

      sta (miss1),y
      mva m0pf kollm12
      sty yschuss1
      lda #0

      dey
      dey
      dey
      sta (miss1),Y
      iny
      iny
      sta (miss1),y

      lda #4      
      ldy yschuss2
      iny
      iny
      sta (miss1),Y
      mva m1pf kollm2
      lda #4
      iny

      sta (miss1),y
      mva m1pf kollm22
      sty yschuss2
      lda #0
      dey
      dey
      dey
      sta (miss1),Y
      iny
      iny
      sta (miss1),y

      lda #16     
      ldy yschuss3
      iny
      iny
      sta (miss1),Y
      mva m2pf kollm3
      lda #16
      iny
      sta (miss1),y
      mva m2pf kollm32
      sty yschuss3
      lda #0
      dey
      dey
      dey
      sta (miss1),Y
      iny
      iny
      sta (miss1),y

      lda #64 
      ldy yschuss4
      iny
      iny
      sta (miss1),Y
      mva m3pf kollm4
      lda #64
      iny
      sta (miss1),y
      mva m3pf kollm42
      sty yschuss4
      lda #0
      dey
      dey
      dey
      sta (miss1),Y
      iny
      iny
      sta (miss1),y

      mva #1 hitclr   

      #if .byte kollm1>#0 .or .byte kollm12>#0
      mva hposm0 xschuss
      mva yschuss1 yschuss
      mva #8 hposm0
      mva kollm1 kollges
      mva kollm12 kollges2
      #end

      #if .byte kollm2>#0 .or .byte kollm22>#0
      mva #8 hposm1
      mva kollm2 kollges
      mva kollm22 kollges2
      #end

      #if .byte kollm3>#0 .or .byte kollm32>#0
      mva #8 hposm2
      mva kollm3 kollges
      mva kollm32 kollges2
      #end

      #if .byte kollm4>#0 .or .byte kollm42>#0
      mva #8 hposm3
      mva kollm4 kollges
      mva kollm42 kollges2
      #end

      mwa #vbinter $224

      pla
      tay
      pla
      tax
      pla
      jmp xitvbv      ;vb-interrupt wird über xitvbv beendet!!

  .endp

Ich hoffe ich nerve oder langweile hier keinen mit meinem Projekt - allerdings, muss man ja auch nicht lesen ... 😉

Mein Zwischenfazit bislang:

  1. Ich lerne jeden Tag den Atari besser kennen und werde immer sicherer in Assembler.
  2. Es gibt unglaublich viele Möglichkeiten und aber auch Tücken - mein Respekt gegenüber den Programmierern von damals ist deutlich gestiegen - toll, was die aus der Kiste rausgeholt haben!
  3. Wir haben ganz klare Limitationen hinsichtlich Zeit und Größe des Programmes - es geht vieles aber nicht alles und man muss sein Projekt wirklich sehr gut planen.
  4. Und genau das macht es aus... sich ständig neuen Herausforderungen ausgesetzt sehen, grübeln grübel grübeln und Lösungen finden und umsetzen. Und genau darum haben die meisten alten Programme auch so viel Charme - nämlich weil da so viel Arbeit, Hirnschmalz und Liebe drinsteckt....
  5. Mein Projekt wird wohl noch einige Monate verschlingen, denn es soll gut und spielbar werden... und dann freue ich mich schon auf das nächste schöne Projekt, wo ich viele Dinge primär ganz anders plane....

Gruß Peter

AntwortZitat

Hi Peter, deine Berichte sind spannend, auch wenn ich noch nie ein Spiel geschrieben habe.

Zu deinen permanenten Zeitproblemen im VBI folgende Idee, die aber evtl. auch vollkommen sinnlos ist:

Das Hauptprogramm ist nach meinem Verständnis üblicherweise eine Dauerschleife. So ungefähr:

main  jsr tue_dieses
  jsr tue_jenes
  jsr mach_was_tolles
  jmp main

Wenn du jetzt die Dinge, die nicht innerhalb des VBI, sondern nur je einmal pro VBI ablaufen sollen, in eine diese Unterroutinen legst und dort verifizierst, dass sie nur einmal je VBI ausgeführt wird, solltest du eine ganze Menge Zeit zur Verfügung haben.

tue_jenes
  lda RTCLOK+2  ; wird im Stage 1 VBI automatisch inkrementiert
  cmp letztes_mal
  bne mach_weiter
  rts
mach_weiter
  sta letztes_mal
; Mach all die tollen Dinge, für die im VBI keine Zeit ist
  rts

letztes_mal
  .byte $00
AntwortZitat

Hi. Ich finde es auch interessant wie das Spiel entsteht. Und stark ist auch das Peter es gleich in Assembler angeht. Aber learning by doing, wie man so schön sagt. Durchhaltevermögen ist ja scheinbar da.

Ich habe heute von Cas ein paar Zong-Hefte bekommen und durchgeblättert. Da sind immer Berichte/Kurs zu Assembler drin. Interessant könnte die Ausgabe 3-4/94 sein. Da geht es um Scrolling in Assembler. Am Ende wird ein Beispiel vorgestellt in dem in einer Landschaft rumgescrollt wird. Zwar rechts/links, aber besser wie nix 😁 . In der nächsten Ausgabe sollte das weiter entwickelt werden, aber die habe ich nicht. Gibt es aber bestimmt irgendwo online. Disketten gab es auch dazu. In einer Ausgabe war auch eine PM-Routine drin, aber nur auf Diskette.

Kannst ja mal nachlesen. Vielleicht hilft ja das eine oder andere was.

Gruß Wolfgang

AntwortZitat

... Ihr Lieben, vielen Dank für die Rückmeldungen und vielen Ideen. Das tut gut und spornt an... und alle Ideen und Tips sind mehr als willkommen. Zong Hefte .... ich suche mal! Schönen Abend allen! Gruß Peter

AntwortZitat

Was macht mein kleines Projekt? In den letzten Wochen hatte ich sehr viel an verschiedenen Dingen programmiert und experimentiert... und mich ein wenig verrannt. Ich bin dann mal einen Schritt zurückgegangen und habe eine etwas ältere aber stabil funktionierende Version genommen und da weitergearbeitet. Ich kann jetzt nicht das ganze Programm komplett ändern, möchte es aber fertigstellen und es funktioniert dann nach den ursprünglichen Kriterien. Ich habe nicht 4 sondern nur 2 Schüsse und die laufen abwechselnd und nicht zugleich. Das war das ursprüngliche Konzept und dabei bleibt es jetzt. Der VBI ist etwas schlanker geworden, aber noch recht voll. Da passt nicht mehr viel rein, braucht es aber auch nicht. Die Schüsse funktionieren jetzt und auch die leidliche Kollision funktioniert zu 98% ohne Fehler. Es gibt jetzt einen ständigen Hintergrundsound, die Explosion der Items funktioniert stabil und mit Sound und die Schüsse laufen jetzt auch mit Sound. Am Sound werde ich später noch arbeiten und vielleicht implementiere ich noch die xSFX Engine ins Programm. Die jetzige Engine ist brutal einfach und mini... geht aber zunächst.

Bevor ich dann mit der Landschaftsgestaltung weitermache und dann noch die nächsten Features reinbringe, will ich nochmal die Explosion angehen. Das gefällt mir noch nicht, da eine Explosion immer zu einem kleinen Programmstop führt. Meine Idee dafür sieht folgendermaßen aus: Im Moment printet das Programm hintereinander mit kleiner Warteschleife die 4 Explosionsphasen über das Item bis es weg ist... Phase 4 ist alles 0 also weg. Die Lösung soll so sein: Die Explosion wird erkannt, das Item wird mit dem ersten Explosionscharakterset überschrieben, dann wird der erste Explosionscharakterset während das Programm weiterläuft mit den 3 weiteren Phasen überschrieben und so läuft die Explosion weiter während das ganze Programm weiterläuft. Theorie glasklar, Umsetzung nicht ganz einfach, da auch das ganze Timing stimmen muss..... Zum Glück habe ich seit einer Woche Freund Omikron in den Knochen und bin entsprechend zuhause und finde etwas Zeit das zu programmieren....

Gruß Peter

AntwortZitat

der Code im Hauptprogramm:

    org $2000

      icl '../hardware.txt'
      icl 'header.txt'
      icl 'character.asm'
      icl 'lands.asm' 
      icl 'pmg_vars.asm'
      icl 'VBI.asm'

      .proc main

main1   mwa #dlist 560  
      mva #151 fuelzaehleritem
      mva #0 fuelzaehler
      mva #10 store1
      mva #170 store3
      mva #16 sound12
      jsr text

Start1    
      jsr variablensetzen     
      jsr pmvorbereiten
      ldy #0
      ldx #0
      ldx #>vbinter     ;VB-Interrupt VektorHi
      ldy #<vbinter     ;VB-Interrupt VektorLo
      lda #7          ;Deferred Mode mit lda #7 festlegen
      jsr setvbv        ;Vektor für die eigene Routine über setvbv eintragen      

hauptprogramm

      ;jsr kollplayer

      jsr soundschuss
      jsr blinken
      jsr letztereihe     ;letzte Reihe (lands) Bildschirm1 printen (sichtbar)  
      jsr feinscroll      ;Feinscroll Bildschirm1 ausführen (sichtbar)    
      jsr grobscroll      ;Bildschirm1 kopieren + grobscroll
      jsr umschalten
      jsr incfuelzaehler
      jsr kollmissile

      ;Ende der Bildschirmausführung / Kontrolle Durchläufe
      sec
      lda #45   ; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
      sbc var6+1
      bpl @+
      jmp start1      ;Stop hier
@     jmp hauptprogramm       ;weiter

      .endp

      ; ---------------------------- S U B R O U T I N E N ----------------------------------

  .proc kollplayer

      clc
      lda kollp0
      cmp #1
      bcc @+
      mva #0 kollp0
@     rts
  .endp 
  .proc kollision
      ldx #0
      clc
@     inx
      cpx #255
      bcc @-
      rts
  .endp 
  .proc umschalten
      ldy #4        ;Bildschirme umschalten von unsichtbar auf sichtbar 
      mva sdlstl var5
      mva sdlstl+1 var5+1
      lda var1
      sta (var5),y
      iny
      lda var1+1
      sta (var5),y

      rts
  .endp 
  .proc wartes
      clc
        ldx delay ; Warteschleife
st      lda RTCLOK+2    
wa      cmp RTCLOK+2    
          beq wa    
          dex            
          bpl st 
          rts
        .endp        
    .proc warte2

      clc
@     dec delay1
      lda delay1
      cmp #1
      bne @-


        rts

      .endp         
  .proc feinscroll
      ldy #1
      mva #0 delay
      mva #255 delay1
@     jsr wartes
      sty vscrol
      iny
      cpy #8
      bne @-  
      inc schussi

      #if .byte schussi=#1
      mwa #$7508 var2     ;var1 auf 29960 ($7508) setzen
      mwa #$7b0C var1 
      #end
      #if .byte schussi=#2
      mwa #$7530 var1     ;var1 auf 30000 ($7530) setzen
      mwa #$7AE4 var2     ;var2 auf 31460 ($7AE4) setzen
      #end

      rts
        .endp   
    .proc schusslogik


        #if .byte strig0=#0 
        asl schussi

      #end

      #if .byte schussi=#2
      lda xposp1 
      sta hposm0

      lda #0
      ldy yschuss1
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss1
      asl schussi
        mva #1 schussi

      #end

      #if .byte schussi=#8
      lda xposp1 
      adc #12
      sta hposm1
      lda #0
      ldy yschuss2
      sta (miss1),y
      lda yposp1
      adc #9
      sta yschuss2
      mva #1 schussi
      #end
        rts

      .endp
  .proc grobscroll  
      ;Den Bildschirm um eins hoch / Grobscrolling um eine Zeile

      ldx #22
@     ldy #$28
      clc
@     lda (var1),y 
      sta itemex
      #if .byte itemex=#68
      jsr fuel
      #end
      sta (var2),y
      dey
      bpl @-
      clc
      lda var1
      adc #$28
      sta var1
      bcc @+
      inc var1+1
@     clc
      lda var2
      adc #$28
      sta var2
      bcc @+
      inc var2+1      
@     clc
      dex
      bpl @-3
      #if .byte schussi=#1
      mwa #$7530 var1     ;var1 + var2 auf 30000 ($7530) setzen
      mwa #$7530 var2
      #end
      #if .byte schussi=#$2
      mwa #$7b0C var1     ;var1 + var2 auf 31500 ($7B0C) setzen
      mwa #$7b0C var2
      mva #0 schussi
      #end

      rts
  .endp       
  .proc letztereihe
      ;Die letzte Reihe printen 
      ;Start der letzten Reihe bei var1 - Line 22
      ;in Var6 (+1) wird die Position von lands gespeichert
      ;in Var5 gehen Infos der Boarderanzahl rein
      ;in y ist der Zähler für letzte Reihe
      ;x wird als Zähler fürs printen benutzt
      clc
      lda var1+1
      ;sta var8+1
      ;sta var7+1
      lda var1
      ;sta var8
      ;sta var7
      adc #112
      sta var1
      inc var1+1
      inc var1+1
      inc var1+1
      ldy #0
      clc
      lda (var6),y  ;Boarderanzahl 1 holen
      sta var5
      tax       ;Boarderanzahl 1 in x speichern
      jsr var6up
      lda (var6),y  ;Boarderart 1 holen
      sta var7    ;abspeichern in var7
@     iny
      sta (var1),y  ;Boarder1 printen
      dex
      bpl @-  
      jsr var6up
      lda (var6),y  ;Boarderanzahl 2 holen
      tax
      jsr var6up
      lda (var6),y  ;Boarderart 2 holen
      ldy var5
@     iny      
      sta (var1),y  ;printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda (var6),y  ;Rand Boarder2 holen
      inc var5    ;Zeilenzähler eins weiter
      ldy var5  
      sta (var1),y  ;Rand Boarder1 printen
      jsr var6up
      lda(var6),y   ;leer holen
      tax
      lda #0
      ldy var5      
@     iny      
      sta (var1),y  ;leer printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Rand Boarder3 holen
      ldy var5
      iny
      sty var5
      sta (var1),y  ;Rand Boarder3 printen
      jsr var6up
      lda(var6),y   ;Boarder4 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder4 printen
      dex
      bpl @-
      sty var5    ;Zeilenzähler sichern
      jsr var6up
      lda(var6),y   ;Boarder5 holen
      tax       ;Boarderanzahl in x speichern
      jsr var6up
      lda (var6),y
      ldy var5
@     iny
      sta (var1),y  ;Boarder5 printen
      dex
      bpl @-
      jsr var6up
      lda (var6),y  ;Sonderitem holen
      sta var5    ;Item in Var5 speichern
      #if .byte var5=#99
      jmp *
      #end
      jsr var6up
      #if .byte var5=#50  ;Öltank printen
      ldx #11
      clc
@     mva tankol,x pr1,x
      dex
      bpl @-
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Fueltank printen
      #end

      #if .byte var5=#51  ;Rakete printen
      ldx #11
      clc
@     mva rakete,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Rakete printen
      #end

      #if .byte var5=#52  ;Alien printen
      ldx #11
      clc
@     mva alien,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;Alien printen
      #end
      #if .byte var5=#53  ;TNT printen
      ldx #11
      clc
@     mva tnt,x pr1,x
      dex
      bpl @-  
      #if .byte tank1x=#0
      mva var1 tank1y
      mva var1+1 tank1y+1
      sec
      lda tank1y
      sbc #120
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      #end
      lda (var6),y    ;Startposition des Items in y speichern
      sta tank1x
      tay
      jsr fuel      ;TNT printen
      #end
      jsr var6up
      mva #0 vscrol
      sec
      lda tank1y
      sbc #40
      sta tank1y
      lda tank1y+1
      sbc #0
      sta tank1y+1
      lda tank1x
      tay
      mva #0 var5

      rts

var6up    clc
      lda var6
      adc #1
      sta var6
      ldy #0
      lda var6+1
      adc #0
      sta var6+1

      rts
  .endp       
  .proc fuel
      sec       ;Routine um den Öltank zu printen - es werden 12 Character meanderförmig geprinten 3x4 Matrix
      lda var1
      sbc #160
      sta var2
      lda var1+1
      sbc #0
      sta var2+1
fuelex    lda pr1
      sta (var2),y  ;1

      lda pr2
      iny
      sta (var2),y  ;2

      lda pr3
      iny
      sta (var2),y  ;3
      clc
      lda var2
      adc #41
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dey

      lda pr4
      sta (var2),y  ;4
      dey

      lda pr5
      sta (var2),y  ;5
      dey

      lda pr6
      sta (var2),y  ;6
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1

      lda pr7
      sta (var2),y  ;7

      lda pr8
      iny
      sta (var2),y  ;8

      lda pr9
      iny
      sta (var2),y  ;9 
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1

      lda pr10
      sta (var2),y  ;10
      dey

      lda pr11
      sta (var2),y  ;11
      dey

      lda pr12
      sta (var2),y  ;12
      tya
      rts
  .endp 
  .proc kollitem          
              ;var8 unveränderter Bildschirmanfang      
      lda yschuss1  ;in Gr.0 -32 (sichtbarer Bereich ab 32 und /8
      sec
      sbc #32
      clc
      ror
      clc
      ror
      clc
      ror
      sta yschuss1  ;y-Position in das x-Register schreiben
      tax 
      dex       ; und einen abziehen
      lda xschuss1  ;x-Position -48 (sichtbarer Bereich)und /4
      sec
      sbc #48
      clc
      ror
      clc
      ror
      tay       ;in y geht die x-Position
      sec
      mva var1 var2   ;holen der Bildschirmadresse -> var2
      mva var1+1 var2+1
      clc
@     lda var2    ;jetzt die y-Position auf die richtige Höhe stellen
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      dex
      bpl @-      ;die y-Position steht in x - Addition von x Zeilen
@     dey       ;die korrekte x-Position einstellen
      lda (var2),y  ;linken Rand checken
      sta var8    
      iny
      iny
      lda (var2),y  ;rechten Rand checken
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0  ;Position nach rechts anpassen 
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0  ;Position nach links anpassen
      dey
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      iny
      iny
      lda (var2),y
      sta var9
      dey
      dey
      #if .byte var8=#0 .and .byte var9>#0
      iny
      #end
      #if .byte var8>#0 .and .byte var9=#0
      dey
      #end
      lda (var2),y    ;Korrektur der y-Position
      sta var8      ;in var8 aktuelle BS-Position
      sec
      lda var2      ;eins drüber - bleibt wenn var2 zu tief
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y    ;lade Bildschirminhalt eins drüber
      sta var9      ;das geht in var9 rein
      #if .byte var8>#0 .and .byte var9=#0  ;alte Position var2 
      clc                   ;wiederherstellen
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0  ;alte Position var2
      clc                   ;eins runter
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      lda (var2),y    ;2. Durchgang der Anpassung um letzte 
      sta var8      ;Fehler zu beseitigen
      sec
      lda var2
      sbc #40
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      lda (var2),y
      sta var9
      #if .byte var8>#0 .and .byte var9=#0
      clc
      lda var2
      adc #40
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte var8=#0 .and .byte var9=#0
      clc
      lda var2
      adc #80
      sta var2
      lda var2+1
      adc #0
      sta var2+1
      #end
      #if .byte kollges=#1
      sec
      lda var2
      sbc #80
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      #end
      #if .byte kollges=#8
      sec
      lda var2
      sbc #80
      sta var2
      lda var2+1
      sbc #0
      sta var2+1
      #end
                ;ab hier stimmt die Position des Items (meistens)
                ;in der Variable y für x-Position
                ;und in var2 für die y-Position 
expl11    
      mva var2 tank1pos   ;y-Position für Explosion1
      mva var2+1 tank1pos+1
      mva #96 audf1
      mva #32 audc1
      mva #222 audf2
      mva #32 audc2
      inc audc1
      inc audc2
      ldx #11
      clc
@     mva expl1,x pr1,x
      dex
      bpl @-  
      jsr fuel.fuelex
      inc audc1
      inc audc2
      tay
      iny
expl22    
      mva tank1pos var2
      mva tank1pos+1 var2+1
      ldx #11
      clc
@     mva expl2,x pr1,x
      dex
      bpl @-  

      inc audc1
      mva #1 delay
      jsr wartes
      inc audc2
      inc audc1
      jsr fuel.fuelex

      tay
      iny
expl33    
      ldx #11
      clc
@     mva expl3,x pr1,x
      dex
      bpl @-  
      mva tank1pos var2
      mva tank1pos+1 var2+1
      inc audc2
      inc audc1
      mva #1 delay
      jsr wartes
      jsr fuel.fuelex
      inc audc1
      inc audc2
      tay
      iny
expl44    
      ldx #11
      clc
@     mva expl4,x pr1,x
      dex
      bpl @-  
      mva tank1pos var2
      mva tank1pos+1 var2+1
      inc audc1
      inc audc2
      mva #1 delay
      jsr wartes
      inc audc1
      inc audc2
      jsr fuel.fuelex
      tay
      iny

      rts
  .endp 
  .proc incfuelzaehler

      inc fuelzaehleritem
      lda fuelzaehler
      tax
      lda fuelzaehleritem
      sta 31043,x
      sta 32543,x
      #if .byte fuelzaehleritem=#155
      mva #151 fuelzaehleritem
      inc fuelzaehler
      #end
      #if .byte fuelzaehler>#200
      mva #0 fuelzaehler
      #end
      #if .byte fuelzaehler=#20
      mva #52 color3
      #end
      #if .byte fuelzaehler>#34 .and .byte fuelzaehler<#200
      ;jmp main1
      mva #0 fuelzaehler        ;Fuel zuende Neustart
      #end
      mva #0 audc1
      rts



  .endp
  .proc text
      ldx #0
      lda #52
      jsr prte
      inx
      lda #45
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #31
      jsr prte
      inx
      lda #52
      jsr prte
      inx
      lda #49
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #54
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #0
      jsr prte
      inx
      lda #51
      jsr prte
      inx
      lda #47
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #42
      jsr prte
      inx
      lda #50
      jsr prte
      inx
      lda #53
      jsr prte
      inx
      lda #0
      jsr prte 
      inx
      lda #55
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #32
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #34
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #54
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #0
      jsr prte 
      inx
      lda #51
      jsr prte 
      inx
      lda #52
      jsr prte 
      inx
      lda #50
      jsr prte 
      inx
      lda #44
      jsr prte 
      inx
      lda #45
      jsr prte 
      inx
      lda #47
      jsr prte 
      inx
      lda #48
      jsr prte 
      inx 
      lda #0
      jsr prte      

      ldx #0    ;Fuel
      lda #46
      jsr prte2
      inx
      lda #31
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #48
      jsr prte2

      ldx #10   ;Score
      lda #53
      jsr prte2
      inx
      lda #43
      jsr prte2
      inx
      lda #50
      jsr prte2
      inx
      lda #52
      jsr prte2
      inx
      lda #45
      jsr prte2
      inx
      lda #0
      jsr prte2
      inx
      lda #160
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      inx
      lda #32
      jsr prte2
      ldx #23   ;Ships
      lda #53
      jsr prte2
      inx
      lda #47
      jsr prte2
      inx
      lda #33
      jsr prte2
      inx
      lda #51
      jsr prte2
      inx
      lda #53
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      inx 
      lda #0
      jsr prte2
      inx
      lda #28
      jsr prte2
      inx
      lda #29
      jsr prte2
      ldx #0
fuellauf  
      clc
      lda fuelzaehleritem
@     jsr prte3
      inx
      cpx #36
      bne @-
      rts
prte    sta 30923,x
      sta 32423,x
      rts
prte2   sta 31003,x
      sta 32503,x
      rts
prte3   sta 31043,x
      sta 32543,x
      rts
  .endp 
  .proc pmvorbereiten

      ; Player vorbereiten und initialisieren
      ; Kollisionen:  4 = Grün   2 = Gelb

      mva #10 yposp1
      mva #120 xposp1
      mva #42 yposm1
      mva #0 xposm1
      mva #94 yposm2
      mva #49 xposm2
      mva #0 tank1x
      mva #0 tank1y

      lda ramtop
      sec
      sbc #16
      sta pmbase
      clc
      adc #3
      sta miss1+1           
      sta miss2+1
      sta miss3+1
      sta miss4+1
      adc #1
      sta play1+1
      adc #2
      sta play3+1
      adc #1
      sta play4+1
      lda #9
      sta play4
      lda #3
      sta play3

      mva #62 sdmctl
      mva #56 pcolr0
      mva #15 pcolr1
      mva #119 pcolr2
      mva #191 pcolr3
      mva #1 gprior
      mva #3 gractl
      mva #1 sizep0
      mva #1 sizep1
      mva #1 sizep2
      mva #0 sizem
      mva #0 rechts
      mva #2 hitclr
      mva #48 blink
      mva #40 p1pf
      mva #8 hposm0
      mva #8 hposm1
      mva #8 hposm2
      mva #8 hposm3
      mva #1 yschuss1
      mva #11 yschuss2
      mva #22 yschuss3
      mva #33 yschuss4
      mva #0 schussi

      mva <lands var6
      mva >lands var6+1
      mva #0 kollp0
      ldy #255        ;Speicher Player 1 leeren
      lda #0
      sta play1
@     sta (play1),y
      sta (play4),y
      sta (play3),y
      dey
      bpl @-
      clc
      ldy yposp1          ;verticale Startpos. Player 1 + füllen
      ldx #0
@     lda pm1,x
      sta (play1),y
      iny
      inx
      cpx #14
      bne @-

      rts

  .end  
  .proc blinken


      lda blink2
      adc #59
      sta blink2
      #if .byte blink2>=#0 .and .byte blink2<#60
      mva #0 blink
      ldx #1
      lda #0
      ldy #2
      mva #250 store1
      jsr sound1
      #end
      #if .byte blink2>=#60 .and .byte blink2<#128
      mva #14 blink
      ldx #1
      lda #0
      ldy #2
      mva #234 store1
      jsr sound1
      #end
      #if .byte blink2>=#128 .and .byte blink2<=#192
      mva #28 blink
      ldx #1
      lda #0
      ldy #2
      mva #218 store1
      jsr sound1
      #end
      #if .byte blink2>=#192 .and .byte blink2<=#255
      mva #42 blink
      ldx #1
      lda #0
      ldy #2
      mva #202 store1
      jsr sound1
      #end


      rts
  .endp
  .proc schuesse

      #if .byte yschuss1>#207 
      ldy yschuss1
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm0
      mva #1 hitclr
      #end
      #if .byte yschuss2>#207
      ldy yschuss2
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm1
      mva #1 hitclr
      #end
      #if .byte yschuss3>#207
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #8 hposm2
      mva #1 hitclr
      #end
      #if .byte yschuss4>#207 
      ldy yschuss4
      dey
      lda #0
      sta (miss1),y
      iny
      sta (miss1),y
      mva #1 hitclr
      mva #8 hposm3
      #end

      rts
  .endp     
  .proc kollmissile

      #if .byte kollges=#4
      mva #15 color3
      sec
      lda fuelzaehler
      sbc #10
      sta fuelzaehler 
      tax
      mva #151 fuelzaehleritem
      clc
      lda fuelzaehleritem
@     sta 31043,x
      sta 32543,x
      inx
      cpx #36
      bne @-
      jsr kollitem
      mva #0 kollges
      #end
      #if .byte kollges=#8
      jsr kollitem
      lda #0 
      sta kollges
      #end
      #if .byte kollges=#1
      jsr kollitem
      lda #0 
      sta kollges
      #end
      rts

  .endp
  .proc variablensetzen

      mva #>chr chbas ;HighByte Character Pointer auf $2000 setzen
      mva #192 gprior ;GTIA Modus 3 
      mva #12 color3  ;Schriftfarbe 
      mva #220 color1 ;Gelb
      mva #153 color0 ;Blau
      ;mva #52 color0 ;Rot
      mva #180 color2 ; Grün
      mva #0 color4 ;Hintergrundfarbe
      lda #0 \ tax \ sta var3 \ sta var4 \ sta var6 \ sta var7 \ sta var6+1 \ sta feuer6
      rts
  .end
  .proc dlist

        .by 112,112,112,100
      .by 30,75
:21     .by 36
:5      .by 4
      .by 65
      .wo dlist
  .endp
  .proc sound1
          ;x Register - Stimme
          ;Akkumulator - Distorsion
          ;y Register - Volumen
          ;Store2 - Frequenz
      pha
      txa
      asl
      tax
      lda store1
      sta audf1,x
      sty store1
      lda #0
      sta audctl
      lda #3
      sta skctl
      pla
      asl 
      asl 
      asl 
      asl 
      clc
      adc store1
      sta audc1,x

      rts

  .endp
  .proc sound2
          ;x Register - Stimme
          ;Akkumulator - Distorsion
          ;y Register - Volumen
          ;Store2 - Frequenz
      pha
      txa
      asl
      tax
      lda store3
      sta audf2,x
      sty store2
      lda #0
      sta audctl
      lda #3
      sta skctl
      pla
      asl 
      asl 
      asl 
      asl 
      clc
      adc store2
      sta audc2,x

      rts

  .endp
  .proc soundschuss
      #if .byte sound12<#16 .and .byte sound12>#0
      ldx #2
      lda #1
      ldy sound12
      mva #2 store2
      dec sound12
      dec sound12

      jsr sound2
      clc
      lda store3
      adc #10
      sta store3
      #end

      #if .byte sound12>=#15
      mva #0 audc2
      mva #0 audf2

      ldx #0
      lda #0
      ldy #0
      mva #170 store3
      mva #0 store2
      jsr sound2
      mva #16 sound12
      mva #170 store3
      #end
      rts
  .end

      run main
AntwortZitat

... heute habe ich es endlich hinbekommen!!

Die Explosion läuft animiert sauber durch während das Programm weiterscrollt... daran arbeite ich jetzt tatsächlich seit Wochen. Eine Idee war ja, daß die Explosion ständig im VBI animiert läuft und man beim Auslösen der Explosion einfach die ständig animierten Charakter auf das Item printet. So kann man letztlich. auch alles animieren wenn es die Zeit zuläßt. Ds habe ich prinzipiell umgesetzt, das Problem dabei ist natürlich, dass die Explosion nie vorbei ist und das explodierende Item quasi explodierend aus dem Bildschirm läuft... fand ich nicht so die beste Lösung. Darum habe ich ja alle 4 Explosionsphasen hintereinander laufen lassen mit kleiner Warteschleife, was dann ganz gut aussieht, was aber immer einen kleinen Ruckler erzeugt... auch blöd.

Gestern habe ich mir nochmal Caverns of Mars 1, 2 und Phobos angeschaut.. und tatsächlich war natürlich Caverns of Mars 1 noch relativ einfach gebaut... man sieht den enormen Fortschritt von CoM 2 und dann zu Phobos... Und hallo... in CoM 1 hat der Programmierer wohl ähnliche Probleme gehabt mit der Explosion, denn er macht es genauso und animiert sie ständig bis sie nach oben rausläuft... bei Phobos hat er es gelöst... dort läuft die Explosion sauber aber relativ langsam...

Mein Lösung nun: Mein Hauptprogramm habe ich mittlerweile relativ übersichtlich, da laufen ständig ein paar Subroutinenaufrufe .. also der Aufbau der letzten Reihe, Fein- und Grobscroll, Umschalten der Bidlschirme und Sound / Blinken. / Kollision. Der VBI läuft ja eh durch. Wenn nun eine Kollision stattfindet, dann ruft das Programm die entsprechende Subroutine auf, hier wird die genaue Position für die Explosion berechnet und korrigiert und dann laufen die 4 Phasen der Explosion hintereinander ab. Zwischen den einzelnen Phasen rufe ich nun einfach die Subroutinen für Feinscroll / Grobscroll / Umschalten und letzte Reihe jeweils auf (also das ganze Hauptprogramm) und das jedes Mal vor den einzelnen Explosionsphasen... zwischendurch muss ich nur noch die y-Position um 40 Einheiten korrigieren (weil er ja um eine Zeile scrollt) und das war es (fast). Das muss ich insgesamt 8 x machen, daher läuft die Explosion recht langsam durch, aber es funktioniert...

Was für ein tricky-Aufwand für diesen scheinbar simplen Effekt....... Morgen lade ich das mal als mov-Datei hoch! LG und gute Nacht Peter

P.s. Es gibt noch viel zu tun, aber so langsam muss ich mir Gedanken für mein nächstes Projekt machen... Ideen für ein schönes Spiel welcome!!

AntwortZitat

Hallo!

Schön zu sehen, dass Du Deine Probleme lösen kannst. Ich habe bei meiner Programmierung nun auch zum 3. Mal restrukturiert. Dafür lernt man aber immer mehr über den ATARI und durch den Lernfortschritt wird das Programm auch kürzer und somit optimierter. Wie im Interrupt-Thread vorgeschlagen, lasse ich in meiner Hauptschleife den Hintergrund am Anfang weiß setzten und zum Schluß wieder schwarz. Die Schleife wird immer direkt hinter einem VBI gestartet. Solange ich kein weiß auf dem Bildschirm sehe, ist die Hauptroutine schnell genug 🙂 Da es bei mir kein Scrolling gibt, habe ich da natürlich einen Vorteil.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Das mit der Schleife ist gut… werde ich beim nächsten Projekt auch so machen… was programmierst du eigentlich, Janko?

AntwortZitat

Ich, ja... naja ist nur so ein Spiel wo Du eine Figur steuerst und Münzen einsammeln musst. Auf Zeichensatzgrafik basierend ohne Feinscrolling und so..

Aber ich habe z.B. einen horizontalen und vertikalen Textscroller im Menü, um diese Techniken zu testen. Dabei nutze ich die empfohlen Displaylist-Methode, wo ich die Displaylist nach 7 Schritte des Feinscrollings manipuliere und so keinen Speicher umkopieren muss. Funktioniert echt Sahne 🙂

Mein Wunsch ist es am Software-Wettbewerb teilzunehmen, auch wenn es nur der letzte Platz werden wird 😳 Deshalb veröffentliche ich auch nichts von meinem Spiel, weil dies leider untersagt ist. Ist aber auch noch viel zu programmieren. Mal sehen, ob ich es überhaupt fertig bekomme.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Also ich würde wohl auch am Software-Wettbewerb teilnehmen, mein Spiel ist ja nicht fertig und "veröffentlicht", insofern sollte das kein Problem sein. Auch stammt der Code komplett von mir, wie man gut nachvollziehen kann... sollte die Kommision dennoch damit "Probleme" haben, dann wäre es auch kein Drama!

Ich werde mal bei Zeiten Sascha fragen, wie die das sehen... spätestens auf der NOMAM werde ich sie ja sehen. Ansonsten wäre ich wirklich sehr sehr interessiert an dem Scrollcode mit der D-List von dir, denn das will ich auf jeden Fall beim nächsten Mal umsetzen und müsste das Rad nicht komplett neu herleiten... 😉

Mein Scrollen verbrät halt richtig CPU Power ... das merkt man dann durchasu 😀

AntwortZitat

Hallo!

Ich habe einmal die von mir genutzte Routine separiert und als eigenes Programm hier eingefügt. Die Systemkonstanten müssen jedoch im selben Pfad liegen und inkludiert werden.

    icl 'Systemkonstanten.asm'

; ########################################################################################################
; ### Speicherbereiche und Variabeln definieren

; Bildschirmspeicher ab $3000
    org $3000

ScrMem01  .byte "                                        "
ScrMem02  .byte "                                        "
ScrMem03  .byte "                                        "
ScrMem04  .byte "                                        "
ScrMem05  .byte "                                        "
ScrMem06  .byte "                                        "
ScrMem07  .byte "                                        "
ScrMem08  .byte "                                        "
ScrMem09  .byte "                                        "
ScrMem10  .byte "                                        "
ScrMem11  .byte "                                        "
ScrMem12  .byte "                                        "
ScrMem13  .byte "                                        "
ScrMem14  .byte "                                        "
ScrMem15  .byte "                                        "
ScrMem16  .byte "                                        "
ScrMem17  .byte "                                        "
ScrMem18  .byte "                                        "            
ScrMem19  .byte "                                        "            
ScrMem20  .byte "                                        "            
ScrMem21  .byte "                                        "            
ScrMem22  .byte "                                        "            
ScrMem23  .byte "                                        "            
ScrMem24  .byte "                                        "

; # Displaylist ab $3400 definieren

    org $3400

DPList    .byte $70,$70,$70       ; 24 leere Scanzeilen (der normale obere Block)   
    .byte $42,<ScrMem01,>ScrMem01   ; Die oberen 2 Zeilen werden nicht gescrollt            
    .byte $42,<ScrMem02,>ScrMem02             
VScrollStart  .byte $62,<ScrMem03,>ScrMem03             
    .byte $62,<ScrMem04,>ScrMem04             
    .byte $62,<ScrMem05,>ScrMem05             
    .byte $62,<ScrMem06,>ScrMem06             
    .byte $62,<ScrMem07,>ScrMem07             
    .byte $62,<ScrMem08,>ScrMem08             
    .byte $62,<ScrMem09,>ScrMem09             
    .byte $62,<ScrMem10,>ScrMem10             
    .byte $62,<ScrMem11,>ScrMem11             
    .byte $62,<ScrMem12,>ScrMem12             
    .byte $62,<ScrMem13,>ScrMem13             
    .byte $62,<ScrMem14,>ScrMem14             
    .byte $62,<ScrMem15,>ScrMem15             
    .byte $62,<ScrMem16,>ScrMem16             
    .byte $62,<ScrMem17,>ScrMem17             
    .byte $62,<ScrMem18,>ScrMem18             
    .byte $62,<ScrMem19,>ScrMem19             
    .byte $62,<ScrMem20,>ScrMem20             
    .byte $62,<ScrMem21,>ScrMem21             
    .byte $42,<ScrMem22,>ScrMem22             
    .byte $42,<ScrMem23,>ScrMem23   ; Die unteren 2 Zeilen werden ebenfalls             
    .byte $42,<ScrMem24,>ScrMem24   ; nicht gescrollt         
    .byte $41,<DPList,>DPList     ; JVB, und die Displaylist wieder starten

; # Scrollschema, um weniger berechnen zu müssen

DPScroll  .word ScrMem03, ScrMem04, ScrMem05, ScrMem06, ScrMem07 
    .word ScrMem08, ScrMem09, ScrMem10, ScrMem11, ScrMem12
    .word ScrMem13, ScrMem14, ScrMem15, ScrMem16, ScrMem17
    .word ScrMem18, ScrMem19, ScrMem20, ScrMem21, ScrMem22
    .word ScrMem03, ScrMem04, ScrMem05, ScrMem06, ScrMem07 
    .word ScrMem08, ScrMem09, ScrMem10, ScrMem11, ScrMem12
    .word ScrMem13, ScrMem14, ScrMem15, ScrMem16, ScrMem17
    .word ScrMem18, ScrMem19, ScrMem20, ScrMem21

VScrollFine .byte $00       ; Finescrolling hier festhalten           
VScrollPos  .byte $02       ; Position des Zeigers für DPScroll
VScrollNext   .byte $00       ; Temporäre-Variable

StoryPos  .word Story       ; Zeiger innerhalb des Textes 

    ;  $FE  = Zeilenende oder 40 Zeichen ausgeben
    ;  $FF  = Text von vorne ausgeben

    ;      0123456789012345678901234567890123456789
Story   .byte "Hier kommt die Textausgabe:",$FE
    .byte $FE
    .byte "Eine volle 40er Zeile benoetigt kein $FE"
    .byte "am Ende",$FE
    .byte $FE,$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "         #             #",$FE
    .byte "         #             #",$FE
    .byte "          #             #",$FE
    .byte "           #             #",$FE
    .byte "            #             #",$FE
    .byte "            #             #",$FE
    .byte "            #             #",$FE
    .byte "           #             #",$FE
    .byte "          #             #",$FE
    .byte "         #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "       #             #",$FE
    .byte "      #             #",$FE
    .byte "       #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "       #             #",$FE
    .byte "       #             #",$FE
    .byte "      #             #",$FE
    .byte "       #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte $FE,$FE,$FE,$FE,$FE,$FF


; ############################################################################
; # VSync
; # 
    .proc WaitVSync

    lda RTCLOK+2
Loop      cmp RTCLOK+2  
          beq Loop

    rts

    .end

; ########################################################################################################
; ### VBI - Routine zum Scrollen

    .proc VBI

    jsr VScroller

    jmp XITVBV

; ### Unterroutinen im VBI

VScroller ; ######## Vertikaler Freinscroller im mittleren Titelbereich ########
    inc VScrollFine
    lda VScrollFine
    cmp #$08
    beq @+        ; Wenn Feinscolling bei 8 dann Grobscrolling

    sta VSCROL    
    rts

@   ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
    lda #$00      ; Feinscrolling auf 0 setzen
    sta VScrollFine
    sta VSCROL

    ldx VScrollPos      ; 20 Zeilen werden gescrollt 
    cpx #$28      ; Danach wieder auf 0 setzen
    bcc @+
    ldx #$00
    stx VScrollPos

@   txa       ; Damit X und Y nicht von 0 zählen
    clc       ; müssen, wird er Endwert für X
    adc #$28      ; berechnet. Nun kann man direkt
    sta VScrollNext     ; hiermit vergleichen

    ldy #$00      ; Y auf Null setzen, jedoch zählt 
            ; Y immer drei Schritte hoch
@   iny       ; pro Durchgang (Befehl, LOMEM, HIMEM)
    lda DPScroll,x      ; LO-Wert holen
    sta VScrollStart,y    ; und in der Displaylist setzen
    inx
    iny
    lda DPScroll,x      ; HI-Wert holen
    sta VScrollStart,y    ; und in der Displaylist setzen
    iny
    inx

    cpx VScrollNext     ; Alle Zeilen abgearbeitet?
    bcc @-

    ; -- Ab hier kommt die Textausgabe 
    ; -- Die natürlich vereinfacht werden kann
    ; -- Wichtig ist, dass der Text ab der Adresse
    ; -- Ausgabe1 bzw. Ausgabe2 augegeben wird

    dex       ; Zurück zur letzten Zeile
    dex
    lda DPScroll,x      ; LO und HI müssen für die
    sta Ausgabe1+1      ; Ausgabe der letzten Zeile
    sta Ausgabe2+1      ; zwei Mal im Programmcode
    inx       ; übertragen werden
    lda DPScroll,x      ; Page 0 ist dann nicht
    sta Ausgabe1+2      ; notwendig
    sta Ausgabe2+2

    inc VScrollPos      ; Die Position fürs nächste scrollen            
    inc VScrollPos      ; setzen

ZeileAusgeben lda StoryPos      ; Nun den Zeiger innerhalb des
    sta Textzeile+1     ; Textes setzen
    lda StoryPos+1      ; und wieder ohne Page 0 direkt
    sta Textzeile+2     ; im Programmcode speichern

    ldx #$00
Textzeile lda $ffff,x     ; Die Adresse zur Ausgabe wird manipuliert    
    cmp #$FE      ; $FE signalisiert, dass die restlichen Zeichen
    beq Zeilenende      ;     Leerzeichen sein sollen.
    cmp #$FF      ; $FF signalisiert, dass der Text von vorne
    beq Textende      ;     ausgegeben werden soll.
Ausgabe1  sta $ffff,x
    inx
    cpx #$28      ; max. 40 Zeichen ausgeben
    bcc Textzeile     
    stx TextNext+1      ; X-Zähler merken

Weiter    clc
    lda StoryPos  
TextNext  adc #$ff      ; Die X gemachten Schritte werden nun auf den
    sta StoryPos      ; Gesamtzeiger addiert
    lda StoryPos+1
    adc #$00
    sta StoryPos+1

    rts       ; Fertig mit dem Grobscrolling und der Zeilenausgabe

Zeilenende  inx       ; Rest Leerzeichen ausgeben
    stx TextNext+1      ; X+1 abspeichern
    dex       ; Nun X wieder einen zurück, um die Ausgabe richtig
            ; zu starten
    lda #" "      ; restlichen Leerzeichen ausgeben
Ausgabe2  sta $ffff,x     
    inx
    cpx #$28      ; bis max. 40 Stück
    bcc Ausgabe2

    jmp Weiter

Textende  lda #<Story     ; Text soll von vorne ausgegeben werden 
    sta StoryPos      ; Hierfür den Zeiger wieder auf den 
    lda #>Story     ; Anfang des Textes setzen
    sta StoryPos+1

    jmp ZeileAusgeben

    .end


; ########################################################################################################
; ### Hauptprogramm

    .proc main

    lda #<DPList      ; Displaylist laden
          sta SDLSTL
    lda #>DPList
    sta SDLSTL+1

    jsr WaitVSync

    ldy #<VBI     ; VBI für einrichten
    ldx #>VBI
    lda #7      
    jsr SETVBV 

    jsr WaitVSync

Loop    jmp Loop

    .end

; ########################################################################################################
    run main

Ich hoffe, dass der Quellcode nachvollziehbar ist. Sicherlich kann man hier noch optimieren.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

... habs gleich mal ausprobiert... sehr geil!! Läuft echt flüssig! Ich schau mir den Code noch ganz genau an, vielleicht kann ich das etwas umbauen und bei mir noch nutzen.... Vielen Dankfür den schönen Code!! LG Peter

AntwortZitat

... nochmal zum Grobscrollcode:

Der Graphikbildschirm hat im Textmodus 24 Zeilen a 40. Jede Zeile in der Displaylist bekommt also eine 2 eingeschrieben (die ersten 24 Scanlines bleiben leer). Die erste Zeile hat dabei nicht den Wert 2 sondern 66 (64+2) - wobei die 64 einen Adressbefehl darstellt - nämlich den des Bildschirmanfanges. Es folgen dann die 23 nächsten Zeilen mit dem Wert 2 und danach kommt noch der Sprungbefehl mit Adresse des Displaylistanfanges.

Nun möchten wir folgendes machen: In jede Zeile schreibe ich statt einer 2 eine 66 (alles dezimal) rein mit der jeweiligen um eine Zeile höheren Adresse für den Bildschirm: 66 64 156 (40000) 66 104 156 (40040) 66 144 156 (40080) 66 184 156 66 224 156 .......... usw am Ende wieder der Sprungbefehl für den Start der Displaylist.

Als nächstes (mein Grobscroll) kopiere ich einfach die Displaylist um - verschiebe also alle Zeilen um eins nach oben: 66 104 156 66 144 156 66 184 156 66 224 156 66 08 157 ..... 66 64 156 Sprungbefehl Displaylistanfang

die letzte Zeile vor dem Sprungbefehl müsste dann wohl immer die vorherige erste sein. Damit bekomme ich ein fortlaufendes Grobscroll des gesamten Bildschirmes. Will ich jetzt einen Shooter damit machen, überschreibe ich einfach die komplette erste Zeile der Displaylist mit den neuen Landschaftsdaten (meine "letzte Reihe") - anschließend wird die erste Reihe durch Umsortierung der Displaylist letzte Reihe. Theoretisch könnte ich auch ganz einfach 24 verschiedene Displaylist mit entsprechend versetzten Zeilen vorbereiten und dann einfach nur jeweils von Displaylist 1 zu 2 zu 3 zu .... zu 24 umschalten. Die Displaylist wird dann noch so aufgebaut, daß der entsprechende Graphicmodus plus Feinscroll mit drin ist, der Grobscroll wird entsprechend immer einmal nach 7 Feinscrollaktionen durchgeführt.

So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen. Habe ich das korrekt verstanden?? Liebe Grüße Peter

AntwortZitat

Hallo Peter!

Deine Idee direkt umzukopieren, also ohne eine Tabelle, macht die Routine noch etwas smarter.

Hier ein Update:

    icl 'Systemkonstanten.asm'

; ########################################################################################################
; ### Speicherbereiche und Variabeln definieren

; Bildschirmspeicher ab $3000
    org $3000

ScrMem01  .byte "                                        "
ScrMem02  .byte "                                        "
ScrMem03  .byte "                                        "
ScrMem04  .byte "                                        "
ScrMem05  .byte "                                        "
ScrMem06  .byte "                                        "
ScrMem07  .byte "                                        "
ScrMem08  .byte "                                        "
ScrMem09  .byte "                                        "
ScrMem10  .byte "                                        "
ScrMem11  .byte "                                        "
ScrMem12  .byte "                                        "
ScrMem13  .byte "                                        "
ScrMem14  .byte "                                        "
ScrMem15  .byte "                                        "
ScrMem16  .byte "                                        "
ScrMem17  .byte "                                        "
ScrMem18  .byte "                                        "            
ScrMem19  .byte "                                        "            
ScrMem20  .byte "                                        "            
ScrMem21  .byte "                                        "            
ScrMem22  .byte "                                        "            
ScrMem23  .byte "                                        "            
ScrMem24  .byte "                                        "

; # Displaylist ab $3400 definieren

    org $3400

DPList    .byte $70,$70,$70       ; 24 leere Scanzeilen (der normale obere Block)   
    .byte $42,<ScrMem01,>ScrMem01   ; Die oberen 2 Zeilen werden nicht gescrollt            
    .byte $42,<ScrMem02,>ScrMem02             
VScrollStart  .byte $62,<ScrMem03,>ScrMem03             
    .byte $62,<ScrMem04,>ScrMem04             
    .byte $62,<ScrMem05,>ScrMem05             
    .byte $62,<ScrMem06,>ScrMem06             
    .byte $62,<ScrMem07,>ScrMem07             
    .byte $62,<ScrMem08,>ScrMem08             
    .byte $62,<ScrMem09,>ScrMem09             
    .byte $62,<ScrMem10,>ScrMem10             
    .byte $62,<ScrMem11,>ScrMem11             
    .byte $62,<ScrMem12,>ScrMem12             
    .byte $62,<ScrMem13,>ScrMem13             
    .byte $62,<ScrMem14,>ScrMem14             
    .byte $62,<ScrMem15,>ScrMem15             
    .byte $62,<ScrMem16,>ScrMem16             
    .byte $62,<ScrMem17,>ScrMem17             
    .byte $62,<ScrMem18,>ScrMem18             
    .byte $62,<ScrMem19,>ScrMem19             
    .byte $62,<ScrMem20,>ScrMem20             
    .byte $62,<ScrMem21,>ScrMem21             
    .byte $42,<ScrMem22,>ScrMem22             
    .byte $42,<ScrMem23,>ScrMem23   ; Die unteren 2 Zeilen werden ebenfalls             
    .byte $42,<ScrMem24,>ScrMem24   ; nicht gescrollt         
    .byte $41,<DPList,>DPList     ; JVB, und die Displaylist wieder starten

; # Scrollschema, um weniger berechnen zu müssen

VScrollFine .byte $00       ; Finescrolling hier festhalten           
VScrollLast   .byte 57        ; Anzahl wieviele Schritte X gehen muss = (20*3)-3

StoryPos  .word Story       ; Zeiger innerhalb des Textes 

    ;  $FE  = Zeilenende oder 40 Zeichen ausgeben
    ;  $FF  = Text von vorne ausgeben

    ;      0123456789012345678901234567890123456789
Story   .byte "Hier kommt die Textausgabe:",$FE
    .byte $FE
    .byte "Eine volle 40er Zeile benoetigt kein $FE"
    .byte "am Ende",$FE
    .byte $FE,$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "         #             #",$FE
    .byte "         #             #",$FE
    .byte "          #             #",$FE
    .byte "           #             #",$FE
    .byte "            #             #",$FE
    .byte "            #             #",$FE
    .byte "            #             #",$FE
    .byte "           #             #",$FE
    .byte "          #             #",$FE
    .byte "         #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "       #             #",$FE
    .byte "      #             #",$FE
    .byte "       #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte "       #             #",$FE
    .byte "       #             #",$FE
    .byte "      #             #",$FE
    .byte "       #             #",$FE
    .byte "        #             #",$FE
    .byte "        #             #",$FE
    .byte $FE,$FE,$FE,$FE,$FE,$FF


; ############################################################################
; # VSync
; # 
    .proc WaitVSync

    lda RTCLOK+2
Loop      cmp RTCLOK+2  
          beq Loop

    rts

    .end

; ########################################################################################################
; ### VBI - Routine zum Scrollen

    .proc VBI

    jsr VScroller

    jmp XITVBV

; ### Unterroutinen im VBI

VScroller ; ######## Vertikaler Freinscroller im mittleren Titelbereich ########
    inc VScrollFine
    lda VScrollFine
    cmp #$08
    beq @+        ; Wenn Feinscolling bei 8 dann Grobscrolling

    sta VSCROL    
    rts

@   ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
lda #$00      ; Feinscrolling auf 0 setzen
    sta VScrollFine
    sta VSCROL

    lda VScrollStart+1    ; Die Zeile die oben verschwindet 
    sta Ausgabe1+1      ; und unten mit neuen Text erscheint
    sta Ausgabe2+1      ; muss zwischen gespeichert werden

    lda VScrollStart+2    ; Hier noch das Hi-Byte
    sta Ausgabe1+2    
    sta Ausgabe2+2      

    ldx #$00      ; Nun alle Zeilen umkopieren
@   lda VScrollStart+4,x    ; aber nur die Angabe der 
    sta VScrollStart+1,x    ; Speicheradresse
    lda VScrollStart+5,x  
    sta VScrollStart+2,x
    inx       ; 3 Schritte weiter
    inx
    inx
    cpx VScrollLast     ; Alle Zeilen abgearbeitet?
    bcc @-

    lda Ausgabe1+1      ; Nun die gemerkte 1. Zeile
    sta VScrollStart+1,x    ; unten noch anfügen
    lda Ausgabe1+2
    sta VScrollStart+2,x    

    ; -- Ab hier kommt die Textausgabe 
    ; -- Die natürlich vereinfacht werden kann
    ; -- Wichtig ist, dass der Text ab der Adresse
    ; -- Ausgabe1 bzw. Ausgabe2 augegeben wird

ZeileAusgeben lda StoryPos      ; Nun den Zeiger innerhalb des
    sta Textzeile+1     ; Textes setzen
    lda StoryPos+1      ; und wieder ohne Page 0 direkt
    sta Textzeile+2     ; im Programmcode speichern

    ldx #$00
Textzeile lda $ffff,x     ; Die Adresse zur Ausgabe wird manipuliert    
    cmp #$FE      ; $FE signalisiert, dass die restlichen Zeichen
    beq Zeilenende      ;     Leerzeichen sein sollen.
    cmp #$FF      ; $FF signalisiert, dass der Text von vorne
    beq Textende      ;     ausgegeben werden soll.
Ausgabe1  sta $ffff,x
    inx
    cpx #$28      ; max. 40 Zeichen ausgeben
    bcc Textzeile     
    stx TextNext+1      ; X-Zähler merken

Weiter    clc
    lda StoryPos  
TextNext  adc #$ff      ; Die X gemachten Schritte werden nun auf den
    sta StoryPos      ; Gesamtzeiger addiert
    lda StoryPos+1
    adc #$00
    sta StoryPos+1

    rts       ; Fertig mit dem Grobscrolling und der Zeilenausgabe

Zeilenende  inx       ; Rest Leerzeichen ausgeben
    stx TextNext+1      ; X+1 abspeichern
    dex       ; Nun X wieder einen zurück, um die Ausgabe richtig
            ; zu starten
    lda #" "      ; restlichen Leerzeichen ausgeben
Ausgabe2  sta $ffff,x     
    inx
    cpx #$28      ; bis max. 40 Stück
    bcc Ausgabe2

    jmp Weiter

Textende  lda #<Story     ; Text soll von vorne ausgegeben werden 
    sta StoryPos      ; Hierfür den Zeiger wieder auf den 
    lda #>Story     ; Anfang des Textes setzen
    sta StoryPos+1

    jmp ZeileAusgeben

    .end


; ########################################################################################################
; ### Hauptprogramm

    .proc main

    lda #<DPList      ; Displaylist laden
          sta SDLSTL
    lda #>DPList
    sta SDLSTL+1

    jsr WaitVSync

    ldy #<VBI     ; VBI für die Musik einrichten
    ldx #>VBI
    lda #7      
    jsr SETVBV 

    jsr WaitVSync

Loop    jmp Loop

    .end

; ########################################################################################################

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Prodehl schrieb: So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen. Habe ich das korrekt verstanden??

So hatte ich es in meinem Posting gemeint und so habe hinterher auch Lars verstanden (der im Gegensatz zu mir praktische Erfahrung darin hat).

Weiterhin viel Erfolg

AntwortZitat

Die letzten Tage habe ich die Schranken programmiert. Eine Schranke war recht einfach zu machen und kostet mich auch nur einen zusätzlichen Charakter in der schon recht vollen Tabelle. Dieser Charakter wird dann im VBI mit 8 einfachen kurzen Befehlen ständig verändert und im Hauptprogramm wird das dann zusätzlich per Random gemischt und ein - / ausgeschaltet. Diese Schranke kann ich beliebig dick machen. Ich habe es als Sonderitem in den Aufbau der Landschaft integriert und kann die Schranke jetzt also irgendwo frei platzieren. Die 2. Schranke ist auch fertig. Dies ist eine Laufschranke jeweils von rechts nach links und umgekehrt, sowie in Kombination ... das war jetzt zwar nicht schwerer zu programmieren, braucht aber etliche Programmschritte, weil ich es mit ROL und ROR mache, dabei 14 Charakter benötige und jedes Charakter ja 8 Bits hat. Der Rechner macht also bei dieser Schranke ständig 112 Befehlszyklen, was ich leider nicht mehr ohne Ruckeln so einfach in den VBI unterbekomme. Ich habe es also ins Hauptprogramm integriert und wenn alles läuft... also Schranke Scroll usw. ruckelt es ein wenig... das Problem habe ich noch nicht gelöst und werde es wohl so hinnehmen. Man sieht auf jeden Fall, daß der Rechner mit dem Gesamtkonstrukt so langsam hinsichtlich der Kapazität an der Grenze ist... zumindest so wie ich es aufgebaut habe. Das Folgeprogramm werde ich anders konstruieren müssen... Nun baue ich noch viel Landschaft und dann das Endlevel, dann müssen noch die Kollisionsabfragen für das Raumschiff geschaltet werden, Bonusschiffe für erreichten Score, die ganzen kleinen Fehler noch raus und fertig bin ich mit dem Projekt! Hier noch eine kleine Demo mit den beiden Schranken... Liebe Grüße und ein schönes WE Peter

rtp4.3..mov

Anhänge:
AntwortZitat

... jetzt habe ich mal in meiner Feinscroll-Routine mit vcount "gespielt" und siehe da - wenn man das timing richtig setzt ist das unangenehme Ruckeln weg. Und plötzlich habe ich auch wieder Optionen im VBI. Ich kann jetzt die Laufschranke in den VBI integrieren und es läuft super flüssig! Und da geht noch viel mehr Code rein... cool!!

Das timing läuft natürlich anders auf 50 Hz (PAL) als auf 60 Hz ... ich frage das jetzt beim Programmstart durch das Register PAL ab und ändere entsprechend den Wert für das timing. Jetzt läuft das Programm flüssig bei 50 und 60 Hz!

AntwortZitat

Prodehl schrieb: Das timing läuft natürlich anders auf 50 Hz (PAL) als auf 60 Hz ... ich frage das jetzt beim Programmstart durch das Register PAL ab und ändere entsprechend den Wert für das timing. Jetzt läuft das Programm flüssig bei 50 und 60 Hz!

Wenn Du das Timing wirklich korrekt auch auf umgebauten Rechnern haben möchtest (PAL ANTIC im NTSC ATARI), solltest Du nicht über das PAL Register gehen. Man sollte dann in einer kleinen Routine zählen, wie viele VCOUNTs möglich sind. 60 Hz Maschinen schaffen weniger, als 50 Hz Maschinen. Mindestens bis 155 sollte es gehen, dann hast Du ein Gerät mit 50 Hz. Ist der höchste VCOUNT Wert kleiner, hast Du ein 60 Hz Gerät.

Über das PAL Register weiß man aber zuverlässig, ob die Farben angepasst werden müssen.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Hallo!

Das mit dem Zählen ist ein super Hinweis. Habe bis jetzt nur das PAL-Register abgefragt gehabt.

Würdest Du auch so zählen?

@   lda VCOUNT      ; Anzahl der VCounts zählen
    cmp VCOUNT      ; Bei über 155 Schritten      
    beq @-        ; hat man 50Hz, darunter
    bcc @-        ; hat man 60Hz
    cmp #$9b
    bcs IS_50hz

IS_60Hz   lda #$01      
    jmp @+
IS_50hz   lda #$00    
@   sta is60Hz

Grüße Janko

Edit: Hab den Code noch einmal geändert gehabt

Mein 600XL ist virenfrei!

AntwortZitat

Das sieht auf den ersten Blick gut aus.

EDIT: Auf den zweiten aber dann doch wohl nicht.

Nutze am besten eine temporäre Variable zum zählen und vor allem setze am Anfang VCOUNT auf 0. So mache ich das meist:

;50Hz or 60 Hz?
  mva #0 vcount
@ lda vcount
  beq w
  sta temp
  jmp @-
w
  lda temp
  cmp #$9b
  bmi ntsc
;PAL
  mva #0 sixtyhz
  rts
ntsc
  mva #1 sixtyhz
  rts

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Guten Morgen in die Gemeinde, ich habe jetzt alle Schranken und Hindernisse fertig und bin dabei die Landschaft zu erweitern. Ich würde mal sagen, daß ich jetzt insgesamt die Hälfte der Landschaft kreiert habe. Mit dem ganzen Programmcode bin ich jetzt bei ca. 24kB ... da scheint noch etwas Luft, aber ich muss jetzt noch ein paar Sachen ändern. Ich starte mit dem Code jetzt nicht bei $2000, sondern bei $400. Auch musste ich ein paar Variablen umdeklarieren, da der Code da sonst reingrätscht. Ich habe noch freie Slots unterhalb $400 gefunden und benutzt. Ein etwas größerer Part wird noch die Displaylist samt Bildschirm sein. Das fängt bei mir ja bei $7530 (30000) an, entweder schiebe ich das nach ganz vorne - also direkt hinter die Charakter, oder soweit nach hinten wie es geht - da brauche ich ca. 2kB an Platz. Jetzt ist es nämlich so, wenn mein Programm in die $7530 Speicherbereiche reingeht, kommt es zu einem kompletten fatalen Absturz - was ja logisch ist. Vielleicht lege ich die DL und den Bildschirm etwa bei 47000 hin, dann habe ich noch massig Platz für das Programm. Bei meinem nächsten Projekt werde ich vorher mir ganz genau Gedanken machen, wie ich den Speicher optimal nutze... LG Peter

AntwortZitat

Hallo!

Kann man "Return to Phobos" überhaupt dann noch via eines DOS starten, wenn Du den Bereich <$2000 nutzt? Das DOS liegt normal an dieser Stelle. Auch einige Speeder haben sich in dem Bereich einquartiert.

Ich habe mein Programm so geschrieben, dass man mit "Escape" ins DOS zurück kehrt 🙂 Habe dafür mein Programm testweise auf eine ATR geschrieben mit DOS 2.5 und über das DOS geladen.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Laden von Dos … daran habe ich gar nicht gedacht… das werde ich entsprechend noch anpassen, damit man das Spiel normal von Diskette laden kann!

AntwortZitat

Jetzt habe ich das Programm etwas umgestellt ... Programmstart jetzt bei 2048 ($800), Bildschirmausgabe statt 30000 jetzt bei 41000 ($A028). Ich weiß gar nicht, warum ich bei 30000 den Bildschirmstart gesetzt habe... dadurch habe ich für das ganze Programm 15 kB mehr zur Verfügung.... Da passt noch Landschaft rein, Programmcode und Sound...

AntwortZitat

Prodehl schrieb: Programmstart jetzt bei 2048 ($800)

Wenn du es aus dem DOS starten und ggf. wieder dorthin zurückkehren willst, ist das immer noc hviel zu niedrig. Du solltest dann nicht unter $2000 beginnen.

AntwortZitat

Schaue Dir mal das uDOS von @Dietrich an. Dort hast Du zwar keine DOS Oberfläche, aber es bietet grundlegende Funktionen, die so ein Spiel benötigt und bietet möglichst geringe Speichernutzung. Habe gerade nicht den genauen Punkt im Kopf... So etwa ab $940 kann man da ein Programm starten lassen.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Ich habe mich in der Tat noch nicht damit beschäftigt und lediglich am Anfang mal ausprobiert, ob sich das Programm generell auf meinem Atari 130 XE starten lässt. Ich programmiere ja unter Eclipse / MADS und da wird dann eine xex-Datei generiert. Die läßt sich via Fujinet einfach laden. Wie aber bekomme. ich das auf eine normale 5 1/2 Zoll Diskette, wo das startbare Programm ist und wo dann das Programm einfach gestartet wird. Ins DOS zurück müsste man nicht... das ging doch bei den ganzen Spielen früher in der Regel auch nicht!

AntwortZitat

Lieben Dank!! Brauche ich denn überhaupt das DOS?? Ich muss doch nur eine startfähige Diskette mit meinem Programm erstellen (wie das geht weiß ich noch nicht) - wo dann am Anfang irgendwo steht, wohin in den Speicher das Programmgeladen wird und wo dann wohl auch der Start erfolgen soll...?!

AntwortZitat

Hallo!

Es kommt ein wenig darauf an, was Du vor hast. Eine Weitergabe ist sicherlich einfacher, wenn man es mit anderen Programmen von einem DOS heraus aufrufen kann.

Wenn Du nach hinten heraus noch 15kb frei hast, spricht doch nichts gegen eine kompatible Start-Adresse?

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Die übrigen 15 kB sind ja mit Startadresse C00 gerechnet und ich habe für den gesamten geschätzten Rest der Landschaft bereits Platzhalter drin - d.h. ich brauche noch ein paar KB für Sound und Code... wenn alles fein ist, dann werde ich den Programmstart so gestalten, daß ein DOS bequem reinpasst! Liebe Grüße

AntwortZitat

Prodehl schrieb: Brauche ich denn überhaupt das DOS?? Ich muss doch nur eine startfähige Diskette mit meinem Programm erstellen

Das ist im Prinzip korrekt. Für eine Bootdiskette benötigst du nur im ersten Sektor einen kleinen Header von sechs Byte, der dem Atari sagt, wieviele Sektoren er booten soll, wohin im RAM die geladen werden sollen und wo die (endgültige) Startadresse liegt. "endgültig" weil nach dem Bootvorgang automatisch an Ladeadresse+6 zur Initialisierung gesprungen wird. Nur wenn das Init mittels RTS beendet wird, erfolgt der Sprung zur Startadresse aus dem Header. Das ist ein bisschen wie beim DOS mit RUNAD $2e0 und INITAD $2e2.

ABER: Häufig wird ein Programm nicht an ein Stück assembliert, sondern ist verteilt auf verschiedene Bereiche im RAM, die du vorher durch org-Befehle definiert hast. Das DOS ist in der Lage, diese Blöcke aus einer XEX-Datei an die jeweils richtige Stelle zu laden. Hast du aber eine Bootdiskette musst du dich mit einem eigenen Lader darum komplett selber kümmern, dass die Daten aus den Sektoren an die richtigen Stellen im RAM kommen. Und vorher musst du aus deiner XEX-Datei diese Blöcke rausschneiden und auf der Bootdiskette entsprechend verteilen.

Deshalb ist echt vorteilhaft, ein DOS zu verwenden.

AntwortZitat

Mit der Option f kann man mit MADS ein komplett hintereinander assembliertes File erzeugen. So geht auch direkt eine eigene Bootdisk. Das habe ich bei der Diskversion von runfast so gemacht. Das komplette atr ist mit MADS erstellt. Am Sonntag kann ich da eventuell etwas source code zu liefern.

Aber ein "normales" com File (oder auch xex) ist letzten Endes einfacher für die Leute zu handhaben.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Sorry, hatte auch heute ordentlich zu tun. Aber jetzt hatte ich mal ein paar Minuten Zeit und hier der versprochene Source Code:

/*
16 bars boot disc based on 510b+ from nyd2022
*/

; @com.wudsn.ide.asm.hardware=ATARI8BIT
; @com.wudsn.ide.asm.outputfileextension=.atr

  opt l-
;---- ATARI addresses
hposp0  = $D000
hposp1  = $D001
hposp2  = $D002
hposp3  = $D003
sizep0  = $D008
sizep1  = $D009
sizep2  = $D00A
sizep3  = $D00B
trig0 = $D010
trig1 = $D011
colpm0  = $D012
colpm1  = $D013
colpm2  = $D014
colpm3  = $D015
colbak  = $D01A
color2  = $D018
gtictl  = $D01B
pmcntl  = $D01D
consol  = $D01F
skctl = $D20F
dmactl  = $D400
pmbase  = $D407
wsync = $D40A
nmien = $D40E
;---
  opt l+

compileto equ $2000
sectors equ ((fin-compileto)/128)+1

  opt f+        ;Activate fill mode
  opt h-        ;no headers
;;; ATR disk header
        .word $0296, $8, $80
:10 .he 00
  org compileto
;--------------------------- boot init
  .proc boot
  .he 00    ;always 0
  dta b(sectors)  ;how many sctors to load
  .wo boot  ;load address
  .wo init  ;init address (seems not to be used)
  jmp start
; mva #$24 710
  .endp
;--------------------------- boot init end
  .proc init
;you can start an intro here
  rts
  .endp
;---------------------------
  .zpvar  .byte ct,wt,mx,shape,rega,regx,posp1,posp0

ri  equ $a0     ;needs 16 bytes
pos equ $b0     ;needs 16 bytes
col equ $c0     ;needs 16 bytes
pmg equ $2000
p0  equ $2000+$400
p1  equ $2000+$500
p2  equ $2000+$600
p3  equ $2000+$700

;---------------------
  .local DL
  .he 70 80
:12 .he 70      ;have to use it on boot disc again
; .ds 96      ;mega cheat :) 12 times $70 or just 96 times 0 if area is clear
  .he 42
  .wo txt
  .he 41
  .wo DL

txt dta d'NYD 2022',d'  16bars_510b+  '*,d' by PPs '

  .endl
;---------------------
  .local dli
  sta rega
  stx regx
  mva posp0 hposp0
  mva posp1 hposp1
  dec posp0
  inc posp1

  mva #%00111001 dmactl ;set screen width (32b,dma,players)
  sta wsync
  mva #$21 gtictl
;--- additional pm
  rol     ;$42  red
  sta colpm2
  rol     ;$84  blue
  sta colpm3
;--- additional pm
;stripes
  ldx #0
@ lda start.area,x
  sta colbak
  and #$7f
  sta colpm0
  sta colpm1
  lda shape
  ror
  ror
  ror
  sta color2
  sta wsync
  inx
  cpx #210
  bne @-
  lda #0
  sta colpm0
  sta colpm1
  ldx regx
  lda rega
  rti
  .endl
;---------------------
  .proc start
  .proc main
  jsr clear_area
  mwa #DL 560
  sta pmbase    ;-> high byte is $20 ;)
  sta 513     ;-> high of DLI is $20, too ;)
  mva <dli 512
;--- set colors     ;.he 00 10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0
  .local setcol
  ldx #15
lx  lda #$f0
  sta col,x
  sub #$10
  sta lx+1
  dex
  bpl lx
  .endl
;---
  stx shape   ;$ff
  stx wt
  stx ct
;---------------------
  .local set_pm
  txa     ;x and a @$ff
@ sta p0,x
  sta p1,x
  dex
  bne @-
;--- additional pm
  ldx #7
; lda #$f0
@ sta p2+113,x
  sta p3+113,x
  dex
  bpl @-
  mva #$70 posp0
  sta posp1
  mva #$40 hposp2
  mva #$a0 hposp3
;--- additional pm
  .endl
;---------------------
  mva #3 sizep0
  sta sizep1
;--- additional pm
  sta sizep2
  sta sizep3
;--- additional pm
  sta pmcntl    ;enable players and missiles
  mva #$c0 nmien    ;DLI + VBI on
lp
;Test ob Ende
/*  lda trig0
  beq @+
  lda trig1
  beq @+
  lda skctl
  and #$04
  beq @+
  lda consol
  and #1
  bne noend
@ jmp $e477   ;cold reset
noend
*/  dec wt
  lda wt
  bpl out
  mva #2 wt
  sta 77
  dec ct
out
;---------------------
  .local stripes
;run thru the 16 stripes
  ldx #15
  stx mx
lp_str
  lda ri,x
  beq hoch
runter
  lda pos,x
  cmp #196
  beq change_up
;runter geht noch
  inc pos,x
  lda pos,x
  tay
  jsr copyshape
  jmp next
change_up     ;up again
  ldx mx
  dec ri,x
hoch
  lda pos,x
  beq change_down
;hoch geht noch
  dec pos,x
  lda pos,x
  tay
  jsr copyshape
  jmp next

change_down     ;down again
  ldx mx
  inc ri,x
  jmp runter
next
  dec mx
  ldx mx
  bpl lp_str
  .endl
;---------------------
  lda ct
  bne lp
  dec ct      ;set back 2 $ff
  jsr chg_shape
  jmp lp
  .endp
;---------------------
  .local copyshape
;first
  lda #0
  sta area,y
;1
  lda col,x
  sta area+1,y
  sta area+12,y
;2
  lda col,x
  ora #2
  sta area+2,y
  sta area+11,y
;3
  lda col,x
  ora #4
  sta area+3,y
  sta area+10,y
;4
  lda col,x
  ora #6
  sta area+4,y
  sta area+9,y
;5
  lda col,x
  ora #8
  sta area+5,y
  sta area+8,y
;6
  lda col,x
  ora #10
  sta area+6,y
  sta area+7,y
;last
  lda #0
  sta area+13,y
  rts
  .endl
;---------------------
  .local clear_area
  ldx #15
@ lda posi,x
  sta pos,x
  lda #1
  sta ri,x
  dex
  bpl @-
  inx
  txa     ;0
@ sta area,x
  dex
  bne @-
  rts
;----------
posi  .he 00 0c 18 24 30 3c 48 54 60 6c 78 84 90 9c a8 b4
  .endl
;---------------------
  .local chg_shape
  jsr clear_area
  inc shape
  lda shape
  cmp #4
  beq sixteenth
  cmp #3
  beq eighth
  cmp #2
  beq quarter
  cmp #1
  beq half
;all        ;was set during clear_area
  rts
half
  ldx #7
  lda #0
@ sta ri+8,x
  dex
  bpl @-
  rts
quarter
  ldx #4
  lda #0
@ sta ri+4,x
  sta ri+12,x
  dex
  bpl @-
  rts
eighth
  ldx #1
  lda #0
@ sta ri+2,x
  sta ri+6,x
  sta ri+10,x
  sta ri+14,x
  dex
  bpl @-
  rts
sixteenth
  ldx #15
  lda #0
@ sta ri+1,x
  dex
  dex
  bpl @-
  stx shape   ;reset shape color value to initial $ff
  rts
  .endl
;---------------------
area        ;area of stripes
; .ds 210     ;not needed on disc boot
;---------------------
  .endp
;---------------------------
fin
  .if <fin < 128
;---
  .rept 128-<fin  ;Sektor noch auffüllen
  .he 00
  .endr
;----
  .else
;----
  .rept 256-<fin
  .he 00
  .endr
;----
  .endif
;---------------------------
  .rept 359-sectors ;SD disc will be our goal
:128  .he 00
  .endr
;---------------------------
;sector 360 := VTOC
;---------------------------
  .he 02      ;DOS 2 DIR
; .he d0 02   ;720 Sectors disc
  .he c5 02
  .he 00 00   ;0 free sectors
  .he 00 00 00 00 00  ;unused space in VTOC
;10-99 -> mark all as used
:90 .he 00
;100-127 -> unused
:28 .he 00
;---------------------------
;Sector 361-368 := DIR
;---------------------------
  .he 22      ;file locked + inuse
  .he 00 00   ;file size in sectors
  .he 00 00   ;start sector number
  dta '-----------'

  .he 22      ;file locked + inuse
  .wo sectors   ;file size in sectors
  .he 01 00   ;start sector number
  dta '16 bars PPs'

  .he 22      ;file locked + inuse
  .he 00 00   ;file size in sectors
  .he 00 00   ;start sector number
  dta '-----------'

  .rept 5
:16 .he 00      ;no file
  .endr

  .rept 7
:128  .he 00
  .endr
;---------------------------
  .rept 352
:128  .he 00
  .endr

Es wird hier eine 720kB "Diskette" direkt mit dem Assembler erzeugt, die das eigene Programm bootet. Es wird auch eine Directory angelegt, die im DOS 2.5 und auch im BiboDos angezeigt wird. Ich habe aber frech die komplette Diskette als belegt markiert und auch nur die Dateilänge des eigenen Programms eingetragen.

Das atr hat aber noch ein paar Probleme - irgendwann untersuche ich das auch mal genauer.

Irgendwo ist es noch nicht komplett kompatibel - zumindest meckern alle Tools am PC. Das atr startet aber problemlos direkt am ATARI (von SD oder auch vom USB-Stick - Diskdrives gehen bei mir momentan beide nicht mehr 😞 ) und im Emulator.

Möchtest Du keine Directory schreiben, nimm Folgendes (ab fin):

fin
;---------------------------
  .if <fin < 128
;---
  .rept 128-<fin  ;Sektor noch auffüllen
  .he 00
  .endr
;----
  .else
;----
  .rept 256-<fin
  .he 00
  .endr
;----
  .endif
;---------------------------
; .rept 1040-sectors  ;noch weitere 1039 Sektoren (MD)
  .rept 720-sectors ;SD
:128  .he 00
  .endr

discboot_16bars_510b+.atr discboot_16bars_510b+.asm

Anhänge:

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Vielen Dank für den Code, aber so ganz habe ich es noch nicht verstanden, wie ich den Code in mein Programm einbinde, damit daraus dann eine Bootdiskette erstellt wird. LG Peter

AntwortZitat

Im Wesentlichen benötigst Du den Code von "compileto. equ $2000 " bis zum Ende von ".proc init". Vor die eigentliche Startroutine Deines Programms kommt das ".proc Start". Dann noch unten ab ".endp" direkt vor "fin" den Rest.

Dein Programm sollte in nach laufender Reihenfolge assembliertes werden, also kein ".org $6000" vor einem ".org $2000" machen. "opt f+" sorgt dafür, dass alles direkt hintereinander assembliert wird ab dem ersten "org".

compileto ist Adresse ab der dann alles im Speicher liegt. Hier kann man dann ohne DOS deutlich runter gehen mit der Startadresse. Nur im Beispielcode geht weniger als $1000 nicht, da ich ja die PMBASE absolut definiert habe und auch nichts lösche...

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

... vielen Dank nochmals! Ich habe das jetzt so in meinen Code eingebaut.

compileto equ $1000

mein Programm startet bei $2000 nach .proc init / .endp beginnt mein Programm mit allen icl und dann mit .proc start

ganz am Ende hinter meinem Programm habe ich dann deine fin Routine gesetzt (brauche ich die?).

Wenn ich den Code aus Eclipse starte kommt nur noch Boot Error (das ist wohl normal). Wenn ich diese Datei als r2phobos.xex direkt starte läuft das Programm. Müsste ich jetzt quasi die r2phobos.xex Datei auf eine Diskette spielen und dann läuft das Programm bootfähig am Atari direkt von der 1050?

AntwortZitat
      /*
16 bars boot disc based on 510b+ from nyd2022
*/

; @com.wudsn.ide.asm.hardware=ATARI8BIT
; @com.wudsn.ide.asm.outputfileextension=.atr


compileto equ $1000
sectors equ ((fin-compileto)/128)+1

  opt f+        ;Activate fill mode
  opt h-        ;no headers
;;; ATR disk header
        .word $0296, $8, $80
:10 .he 00
  org compileto
;--------------------------- boot init
  .proc boot
  .he 00    ;always 0
  dta b(sectors)  ;how many sctors to load
  .wo boot  ;load address
  .wo init  ;init address (seems not to be used)
  jmp start
; mva #$24 710
  .endp
;--------------------------- boot init end
  .proc init
;you can start an intro here
  jmp *
  rts
  .endp
;---------------------------

;---------------------






      org $2000 ;4096



      icl '../hardware.txt'
      icl 'header.txt'
      icl 'character.asm'
      icl 'pmg_vars.asm'
      icl 'VBI.asm'
      icl 'Sfx-Engine.asm'

      .proc start

main1   mwa #40960 bilds1   
      mwa #41000 bilds11    
      mwa #42460 bilds2   
      mwa #42500 bilds21    


      mva #11 wsync
      mwa #dlist 560  
      mva #151 fuelzaehleritem
      mva #0 fuelzaehler
      mva #10 store1
      mva #170 store3
      mva #16 sound12
      jsr text

Start1    

      ;50Hz oder 60 Hz
      mva #0 vcount
@     lda vcount
      beq @+
      sta grafmod
      jmp @-
@     lda grafmod
      cmp #155
      bmi @+
      ;PAL
      mva #50 grafmod
      jmp @+1
@     ;NTSC
      mva #9 grafmod      
@     


      jsr variablensetzen     
      jsr pmvorbereiten
      ldy #0
      ldx #0
      ldx #>vbinter     ;VB-Interrupt VektorHi
      ldy #<vbinter     ;VB-Interrupt VektorLo
      lda #7          ;Deferred Mode mit lda #7 festlegen
      jsr setvbv        ;Vektor für die eigene Routine über setvbv eintragen      


      lda #5
      ldx #2              ; Kanal 1 wählen
            sec                 ; force
            jsr xSFX.START

hauptprogramm
.........
........


......
.......


@     lda #32
      sta scorez2
      sta 42060
      sta 43560
      inc scorez3
      lda scorez3
      sta 42059
      sta 43559

      rts
  .end

      icl 'lands.asm' 

fin
;---------------------------
  .if <fin < 128
;---
  .rept 128-<fin  ;Sektor noch auffüllen
  .he 00
  .endr
;----
  .else
;----
  .rept 256-<fin
  .he 00
  .endr
;----
  .endif
;---------------------------
; .rept 1040-sectors  ;noch weitere 1039 Sektoren (MD)
  .rept 720-sectors ;SD
:128  .he 00
  .endr


      ;run start


AntwortZitat

Alle ORGs im Programm müssen raus. Mit ".ALIGN $1000" kannst Du nachfolgenden Code an den nächsten 1000er binden. ".ALIGN $0400" hilft bei Fonts.

Der letzte Teil schreibt die fehlenden Bytes der "Diskette" also muss das zwingend da sein.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

mein Programm hat ja nur ein org .. also das muss raus! Was ist mit org compileto? Das muss drin bleiben?!

AntwortZitat

Prodehl schrieb: mein Programm hat ja nur ein org .. also das muss raus! Was ist mit org compileto? Das muss drin bleiben?!

Ja, das eine org muss bleiben. Der Atari muss ja wissen wohin er laden soll.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

ok... und dann daraus eine atr erstellen und dann auf eine leere formatierte Diskette speichern?!

Wo steht mein Projekt? Alle Sonderitems sind fertig - die Charaktertabelle ist auch voll! Die Landschaft habe ich weiter ausgebaut, ich denke in den nächsten 1-2 Wochen ist sie auch komplett fertig. Das automatische Scroll hört ja irgendwann auf und dann muss man aktiv selber runterscrollen - das ist auch nötig, da die Hindernisse sonst nicht passierbar sind (im Beispiel unten habe ich es für den Zweck der Landschaftserstellung rausgenommen, normalerweise fährt man mit dem Schiff ganz langsam und vorsichtig durch die Hindernisse). Und genau hier habe ich in den letzten Tagen rumgefeilt. Die Feinscroll-/Grobscrollroutine musste ich extra dafür anpassen, denn man muss ja jeden einzelnen (von den 8) Feinsteps fahren können, nicht - wie vorher - einen kompletten Feinscrolldurchlauf. Das habe ich heute programmiert und jetzt fliegt das Raumschiff sehr flüssig und sehr filigran Step für Step (wenn man es so steuert) weiter. Da musste ich noch etwas Code und Gehirn reinstecken. An die Explosionen muss ich nochmal ran, denn die schöne Lösung der mitlaufenden Explosionen beim automatischen Scroll sind hinderlich, denn wenn das Raumschiff steht und man ballert einen Tank ab, dann kommt automatisch der Scroll rein für die 4 Explosionsphasen... Wenn ich das gefixt habe, kommt der Part mit der Schiffskollision. Das erkennt er schon, aber ich muss die Aktion noch programmieren: Explosion des Schiffes, Verlust eines Schiffes, zurück zu einem vorherigen Punkt gehen, Sound dafür. Dann kommt noch das Auffüllen eines Schiffes bei einem bestimmten Score. Danach gehe ich nochmal ganz intensiv an die Kollisionserkennung. Die ist gerade bei Nahdistanz noch zu fehlerhaft... das will ich perfekt hinbekommen. Wenn das alles fertig ist, kommt der Endgegner - hier bin ich noch völlig blank... irgendetwas cooles muss her. Dann das Intro incl. Sound - der Introsound soll dann während des Spieles leise weiterlaufen... Wie man sieht: Da ist noch viel zu tun!! Ich stelle das Spiel auf jeden Fall fertig und es soll schön spielbar sein! Mein erstes komplettes und komplexes Projekt für Atari!. Ob ich es dann später für den Abbuc-Wettbewerb einreiche... fraglich. Vielleicht hat es zu viele Ähnlichkeiten mit Phobos von damals... vielleicht baue ich die ganzen Grafiken und Charakter später noch um und baue daraus etwas anders... mal sehen!

Und hier noch ein kurzes Video von dem neu erstellten Landschaftspart - wie gesagt, später fährt man hier langsam selbstgesteuert durch:

rtp4.1.mov

Liebe Grüße Peter

Anhänge:
AntwortZitat

Hi! Solange es Deine eigene Kreation ist und Du keine Urheberrechte verletzt, solltest Du damit am Software-Wettbewerb teilnehmen können. Du darfst es nur nicht vorher veröffentlichen... Das ist ja der Punkt, wo ich auch unsicher bin. Sonst hätte ich von meinem Projekt auch mal etwas gepostet 😉

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

Ich stelle ja hier nur Fragmente des Programmes rein und ab und zu mal einen kleinen Ausschnitt als Video. Das Programm so ist ja noch nicht fertig und schon gar nicht spielbar. Sollte das dennoch ein Problem machen, dann ist es halt Pech 😉 Wenn alles fertig ist, möchte ich nach dem Wettbewerb alle Source-Codes noch massiv mit Bemerkungen und Erklärungen versehen und dann veröffentlichen. Da sind so viele Erkenntnisse mittlerweile - und Fallstricke... klar, die Allermeisten sind schon echte Profis und brauchen das sicher nicht, aber etwaige Neueinsteiger was Assemblerprogrammierung angeht, könnte es helfen. Ich gehe da mal von mir selber aus: Mir hätte das enorm geholfen!!!
Ich hatte so viele Probleme zu bewältigen (und da gibt es noch ein paar) - alleine die weiterscrollende Explosion war so tricky... Kollege Christensen hatte damals ja auch so seine Probleme damit und es auch erst bei Phobos richtig gelöst... in Caverns of Mars 1 war das noch nicht der Fall wie man gut auf youtube sehen kann! Caverns of Mars 2 war schon etwas komplexer und bei Phobos hat er alles perfekt programmiert! Schade, daß er danach völlig abgetaucht ist!

AntwortZitat

Prodehl schrieb: ok... und dann daraus eine atr erstellen und dann auf eine leere formatierte Diskette speichern?!

Mit dem Code entsteht direkt eine atr Datei.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Was gibt es Neues? RTP hat eine weitere Facette vor der ich echt richtig Bammel hatte. Das Spiel hat jetzt ein richtig schönes 3-stimmiges Intro mit laufender Hintergrundmusik. Da muss ich jetzt großen Dank an Janko loswerden, der die alte Vorlage aus der Hexenküche (damit sind auch meine ersten Töne entstanden) stark erweitert hat und so eine wirklich schöne aber dennoch schlanke Engine gemacht hat. Diese läßt sich leicht in den asm - Code einbinden! Dann habe ich von ihm noch den Tipp bekommen mir auf fiverr.com für schmales Geld eine 8-bit Retromusik komponieren zu lassen, über eine Partitur kann man dann die Töne und den Takt auslesen und ins System reinbringen... Janko (so viel verrate ich schon mal) schreibt gerade an einen Midi-Analyse-Konverter... damit kann jeder ohne Kenntnisse die Sounds in den Atari einbringen... einfach fantastisch und es funktioniert scho!!! Ich hoffe, daß er dieses Projekt noch verfeinert... nochmals vielen vielen Dank, Janko!! Musik ist drin, nun gehts weiter mit dem Code.... und ich habe noch satte 11kb frei! LG Peter2

AntwortZitat

.... die dreistimmige Musik überlastet jetzt leider den VBI bei 60 Hz. Sauber spielen kann man es jetzt nur im 50 Hz-Modus. Ich mache jetzt erstmal die Landschaft komplett fertig und programmiere das Endlevel und die vielen Kleinigkeiten, die noch notwendig sind. Dann kümmere ich mich um die Kollisionsabfrage (da gibt es noch ein paar Fehler) und dann kommt das Intro. Ich überlege auch, ob ich die Grafik etwas umbaue, damit das Spiel nicht zu nah am Original Phobos ist. Wenn alles fertig ist, kümmere ich mich noch ganz intensiv an der Optimierung des VBI, damit die Hintergrundmusik auch im 60 Hz Modus spielt und das Spiel funktioniert. Falls das nicht klappt, ändere ich die Hintergrundmusik in 2 - oder 1 -stimmig .... aber jetzt erstmal die Landschaft, am liebsten soll die bis zur NOMAM fertig sein!

AntwortZitat

Hi,

Prodehl schrieb: das Teilen durch 8 geht mit drei ROR-Anweisungen!

vielleicht ist es schon aufgefallen, aber falls nicht: wenn man ROR benutzt, kommen die Bits, die man rechts rausschiebt, über und mit Carry wieder links rein:

CLC
$1F = %00011111
ROR -> %00001111 1
ROR -> %10000111 1
ROR -> %11000011 1 -> $C3

Meines Erachtens wäre also LSR richtig.

CU, Erhard

Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.

AntwortZitat

Hallo Erhard, der Post war ja im November und sicherlich noch mit weniger Assembler-Erfahrung meinerseits. Darum habe ich ja auch vor jedem ROR ein CLC gesetzt, die andere Lösung mit LSR ist natürlich besser! An die Kollisionskorrektur muss ich eh nochmal ran, daher habe ich den Code bislang so belassen. Danke aber für den Tip Gruß Peter

AntwortZitat

Was gibt es Neues bei RTP?

Das Intro ist fertig! Mir bleiben für den gesamten Rest jetzt noch 3100 bytes.... Die Landschaft ist fertig, der Sound für die Schüsse und Explosionen sind drin, funktionieren aber noch nicht so richtig gut bzw. nicht mehr... die Kollision für das Raumschiff muss noch rein. Da wird noch etwas Code benötigt und wohl den ganzen Rest verschlingen. Danach kommt die ganze Fehlerbereinigung. Ich habe noch etwas überflüssigen Code drin, den werde ich noch rausschmeissen und so noch etwas Platz schaffen... viel geht aber nicht mehr. Das bedeutet aber, das das Programm auch bald dann fertig ist. Ich denke am meisten Zeit werde ich noch brauchen, um die Fehler zu beseitigen und um Code zu optimieren.... Gruß Peter

AntwortZitat

Hi,

da ist ein Grafikfehler nach dem Textscroller bei ca. Sekunde 19 ...

Schöne Ostern

Erhard

Jede Info, die zu Hause auf meinem Rechner liegt habe ich unterwegs nicht verfügbar. Jede Info, die im Netz liegt finde ich nicht wieder, wenn ich sie benötige.

AntwortZitat

Guten Morgen Erhard, vielen Dank für die Info! Der Fehler tritt auf, wenn man auf Start drückt und das Programm vom Intro (Textscroller) auf Game umschaltet. Ich nutze für das Intro eine andere Displaylist und einen anderen Charakterset... den Fehler kenne ich, habe ihn aber noch nicht lokalisiert... mir fällt gerade was ein, das probiere ich gleich mal aus! Danke für die Inspiration!! Schöne Ostern Gruß Peter

AntwortZitat

....der Bildschirm ist noch nicht leer - beim Umschalten auf den anderen Charakterset wird die Schrift dann entsprechend kryptisch... Ich muss den gesamten Bildschirm löschen beim Umschalten vom Intro zum Hauptprogramm! Jetzt hab ich es (war eigentlich fast klar) ... Danke Erhard!

AntwortZitat

Moin moin, da habe ich mal wieder ein dumme Frage in die Runde: Mein Intro ist fertig... mit Musik und Textscroll... das läuft so munter vor sich hin bis ich Start drücke und dann geht das Spiel los... so die Theorie. Allerdings muss ich manchmal mehrmals auf Start drücken, bis er es erkennt, da das Introprogramm gerade woanders ist. Das ist natürlich blöd, denn wenn man Start drückt, soll es auch gleich losgehen. Ich dachte - schlau wie ich bin - das könne ich im VBI lösen. Denkste. Die 2. Hälfte des VBI schreibt immer #8 in die Consol.... das muss doch besser gehen??? Wo ist hier der Haken? Gruß Peter

AntwortZitat

Hallo Peter!

Ich frag mich gerade wie umfangreich Dein Intro ist, da bei mir das ganze wie folgt aussieht:

    lda #$08
    sta CONSOL

    jsr TitleVBI.An     ; Titel-MUSIK einschalten

Loop    lda #$00      ; Farbwechsel verhindern
    sta ATRACT

    lda CH        ; Prüfen ob ESC gedrückt wurde
    cmp #$1c      
    beq Exit      

    lda CONSOL      ; Prüfen ob START gedrück wurde
    cmp #$06      
    bne Loop      

Exit    jsr TitleVBI.Aus    ; Titel-MUSIK abschalten

Im "TitleVBI" wird die Musik und jegliche Ausgabe gesteuert, so dass die Hauptschleife lediglich die Start- und Esc-Taste ausliest.

Grüße Janko

Mein 600XL ist virenfrei!

AntwortZitat

hmmm ... klar, bei mir läuft alles in der Hauptschleife: Musik, Grob- und Feinscrolling..... Dann baue ich das um und lege das alles in einen VBI und mache die Schleife ganz schlank! Danke für die Eingebung, Janko!!

AntwortZitat

Hallo!

Ich denke nicht, dass es zwingend im VBI liegen muss, es sollte nur möglichst schnell abgearbeitet werden können.

Janko

Mein 600XL ist virenfrei!

AntwortZitat

ok, aber du hast ja auch ein schönes Scrolling im Intro - das läuft doch sicherlich dann im VBI?!

AntwortZitat

Prodehl schrieb: Moin moin, da habe ich mal wieder ein dumme Frage in die Runde: Mein Intro ist fertig... mit Musik und Textscroll... das läuft so munter vor sich hin bis ich Start drücke und dann geht das Spiel los... so die Theorie. Allerdings muss ich manchmal mehrmals auf Start drücken, bis er es erkennt, da das Introprogramm gerade woanders ist. Das ist natürlich blöd, denn wenn man Start drückt, soll es auch gleich losgehen. Ich dachte - schlau wie ich bin - das könne ich im VBI lösen. Denkste. Die 2. Hälfte des VBI schreibt immer #8 in die Consol.... das muss doch besser gehen??? Wo ist hier der Haken? Gruß Peter

Frage doch einfach die Tasten im VBI oder DLI ab und starte dann von dort aus das Spiel.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Ich wollte ja die Start-Taste mit CONSOL im VBI abfragen, der VBI schreibt aber in der 2. Hälfte da immer den Wert 8 rein... DLI wäre noch eine gute Idee...

AntwortZitat

Prodehl schrieb: ok, aber du hast ja auch ein schönes Scrolling im Intro - das läuft doch sicherlich dann im VBI?!

Ja, bei mir läuft alles im VBI, Musik und die beiden Scroller. Die Farbe wird im DLI geändert.

Janko

Mein 600XL ist virenfrei!

AntwortZitat

Frag Start doch einfach im VBI ab und wenn es gedrückt wurde, setz ein Flag. Dieses Flag prüfst du an einer Stelle, die zum Start des Spiels passend ist. Wenn es gesetzt ist, löschst du es wieder und startest das Spiel. Das ist quasi die Umkehr dessen, wie die Schattenregister in Page $2xx verwendet werden.

AntwortZitat

das mit dem Flag setzen habe ich schon versucht… das funktionierte nicht besser… das schaue ich mir nochmal in Ruhe an! Den korrekten DLI Aufruf nach Buch führte bislang zum Absturz… keine Ahnung was ich da falsch mache… ich muss mich nochmal intensiv mit dem DLI beschäftigen! @Janko: Beim Grobscroll im VBI muss du doch ne Menge Daten rumschieben… wird das nicht zeitkritisch??

AntwortZitat

Das "Grobscrolling" erreiche ich durch Displaylistmanipulation, indem ich die Speicheradressen in der Displaylist verschiebe. Das ist dann Ruck-Zuck erledigt.

Hier der Beispiel-Code... aber die Variablenamen bitte ignorieren 😳

@   ; ######## Vertikales Grobscrolling durch Displaylist-Manipulation
    lda #$00      ; Feinscrolling auf 0 setzen
    sta VSCROL

    lda TitelSC2+1      ; Die Zeile die oben verschwindet 
    sta TextNeu1+1      ; und unten mit neuen Text erscheint
    sta TextNeu2+1      ; muss zwischen gespeichert werden

    lda TitelSC2+2      ; Hier noch das Hi-Byte
    sta TextNeu1+2    
    sta TextNeu2+2      

    ldx #$00      ; Nun alle Zeilen umkopieren
@   lda TitelSC2+4,x    ; aber nur die Angabe der 
    sta TitelSC2+1,x    ; Speicheradresse
    lda TitelSC2+5,x  
    sta TitelSC2+2,x
    inx       ; 3 Schritte weiter
    inx
    inx
    cpx TitelScrollLast   ; Alle Zeilen abgearbeitet?
    bcc @-

    lda TextNeu1+1      ; Nun die gemerkte 1. Zeile
    sta TitelSC2+1,x    ; unten noch anfügen
    lda TextNeu1+2
    sta TitelSC2+2,x

Die Displaylist sieht bei mir dazu so aus:

TitelDLst .byte $70,$70,$F0       ; 24 leere Scanzeilen (der normale obere Block)   
    .byte $4D,<TitelGfk,>TitelGfk     ; Grafik 13 (Gr. 7) und Speicherzuweisung   
    .byte $0D,$0D,$0D,$0D,$0D,$0D   ; weitere 25 Zeilen Gr. 7         
    .byte $0D,$0D,$0D,$0D,$0D,$0D     ;             
    .byte $0D,$0D             
    .byte $70,$70,$F0     ; noch weitere leere Scanzeilen         
TitelSC2  .byte $62,<SPScrMem01,>SPScrMem01 ; Ab hier Text Gr. 0 mit vertikales             
    .byte $62,<SPScrMem02,>SPScrMem02 ; Scrollen              
    .byte $62,<SPScrMem03,>SPScrMem03 ;             
    .byte $62,<SPScrMem04,>SPScrMem04 ;             
    .byte $62,<SPScrMem05,>SPScrMem05 ;             
    .byte $62,<SPScrMem06,>SPScrMem06 ;             
    .byte $62,<SPScrMem07,>SPScrMem07 ;             
    .byte $62,<SPScrMem08,>SPScrMem08 ;             
    .byte $62,<SPScrMem09,>SPScrMem09 ;             
    .byte $62,<SPScrMem10,>SPScrMem10 ;             
    .byte $E2,<SPScrMem11,>SPScrMem11 ;             
    .byte $62,<SPScrMem12,>SPScrMem12 ;             
    .byte $42,<SPScrMem13,>SPScrMem13 ;             
    .byte $70,$70,$F0       ; wieder leere Zeilen             
TitelSC1  .byte $56,<TitelScrl,>TitelScrl   ; Gr. 1 mit horizontales Scrolling              
    .byte $41,<TitelDLst,>TitelDLst   ; JVB, und die Displaylist wieder starten

Mein 600XL ist virenfrei!

AntwortZitat

... ich habe jetzt im Immediate-VBI eine kleine Routine drin, die CONSOL abfragt und falls gedrückt ist einen Werte in eine Variable einschreibt, die ich dann später in der Introschleife auslese und entsprechend das Hauptprogramm startet (so wie von DjayBee vorgeschlagen). Da hatte ich wohl vorher einen kleinen Fehler drin... Jedenfalls funktioniert es jetzt bestens! Danke für die Kommentare und Ideen...es ist wirklich super hier im Forum. Jeder hilft jedem. Und es macht echt Spass, sich hier so auszutauschen. @Janko: Dieses Scrolling mit der DL werde ich beim nächsten Projekt umsetzen, das erscheint mir viel besser. Danke dafür! Vielleicht nehme ich dann auch eine Bitmap-Grafik... mal sehen! Gruß Peter

AntwortZitat

Peter, Scrolling im VBI macht es zunächst einfacher immer "im Takt des Systems" zu bleiben. Allerdings muss man halt an die Zeit denken, die gerade bei NTSC Systemen deutlich knapper ist. Für den Sound sollte man am besten immer testen, ob man einen Atari mit 50 oder 60 Hz hat und die Abspielgeschwindigkeit anpassen. Bei manchen Spielen ist das sogar auch für das gesamte Spiel sinnvoll. Auf NTSC sind manche Dinge dann halt schneller, wenn man es nicht anpasst.

Grüße aus Bärlin, Ralf

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Hallo Ralf, vor meinem nächsten Projekt werde ich mir auf jeden Fall Gedanken machen, wo ich wie was mache. Bei RTP habe ich ja relativ wild losprogrammiert und bin dann immer tiefer in die Materie eingetaucht. Bislang konnte ich alle größeren Probleme lösen - weiß aber genau, daß vieles anders vielleicht besser hätte gehen können. So hat mich z.B. das ganze Zeittiming echt immer wieder beschäftigt und oftmals durch notwendige Programmänderungen unerklärliche Ruckler beim Scrolling beschert. So musste ich z.B. die Idee von 4 Schüssen aufgeben, weil ich es einfach nicht mehr sauber hinbekommen habe, ohne das es woanders hakte. Die Ruckler habe ich jetzt mittlerweile ganz gut im Griff durch richtiges Timing von RTCLOK - das Feinscrolling z.B. läuft bei mir im Hauptprogramm und wird durch RTCLOK gesteuert. Die eigentlichen unerklärlichen Ruckler bekomme ich mit der Abfrage PAL oder NTSC in Kombination mit vcount und entsprechenden kleineren Pausen auf vcount getriggert in den Griff. Damit würde ich auch die 4 Schüsse hinbekommen... aber das jetzt alles umzubauen macht keinen Sinn, das setze ich den im nächsten Part um. Auch das ganze Scrolling werde ich anders machen - nämlich mit DL Verschiebungen... vielleicht baue ich dann dann das Spiel in einer Bitmapgrafik auf. Was ich wirklich gelernt habe in den letzten ca. 6 Monaten ist die erstaunliche Komplexität dieses kleinen Rechners. Es gibt so viele Möglichkeiten und aber auch Beschränkungen wo man wirklich gut planen muss... Thema Speicher, Geschwindigkeit, Charakter etc etc.... Liebe Grüße Peter

p.s. Ich habe heute die allererste Betatestversion fertig - das Programm läuft komplett vom Intro zum Spiel - mit Sounds, Musik, Explosionen, Score, Schiffe (man hat 5) werden zerstört, Ende und Rücksprung zum Intro mit möglichem Neustart. Es fehlt noch das Endlevel und etliche Bugs müssen noch fixiert werden, auch ist die Landschaft noch in Teilen zu schwer... das muss noch spielbarer werden! Auf jeden Fall wird am Ende ein komplettes und fertiges Spiel entstanden sein für alle, die Bock drauf haben.... 😉

AntwortZitat

Status Return To Phobos:

Das Spiel ist im Prinzip fertig!

Ich habe im Grunde alle Elemente jetzt drin und man kann das Spiel vom Anfang bis zum Ende komplett durchspielen. Dabei gibt es ein Intro und ein Extro, einen durchgehend scrollenden Part, einen Part wo man aktiv nach unten sich scrollend bewegen muss. Es gibt eingeschobene Zwischenlevel und einen Endgegner, den man besiegen muss. Alle Sounds sind drin incl. der Musik (es gibt drei verschiedene Musikstücke). Die Items habe ich umgearbeitet und das Spiel heisst jetzt auch anders - somit sind auch mögliche alte Rechte gewahrt.

Was ist noch zu tun? Die Landschaft gehe ich jetzt intensiv durch nach guter Spielbarkeit (ein paar Ecken erscheinen zu schwer), es gibt noch ein paar kleine Bugs, die ich bearbeiten muss. Die Kollisionserkennung mit Explosion der Items ist noch zu ungenau - hier werde ich noch Hirnschmalz reinstecken. Dann wird getestet (Janko) und meine Frau kümmert sich noch um den englischen Text (mein Englisch ist naiv).

Freier Speicher für Coding: Noch ca. 1300 Bytes... das reicht noch für Kleinigkeiten, aber ich bin ja auch fertig. Ein aufwendiger Highscore ist da wohl nicht mehr drin... und dann gehts zum Holger 😉

Grüße Peter

AntwortZitat

Status des Spiels: Return To Phobos heißt jetzt Battle Of Eris ! Eris ist ein kleiner Zwergplanet am Rande des Sonnensystems und wurde erst vor ein paar Jahren entdeckt. Meine Geschichte setzt hier an, denn die Aliens sind nach der verlorenen Schlacht auf Phobos nach Eris geflohen und jetzt wieder erstarkt.

Das Spiel ist jetzt fertig. Ich habe noch einen Highscore eingebaut mit insgesamt drei Rankingplätzen, die auch auf Diskette abgespeichert werden. Der Speicher ist jetzt wirklich ausgereizt... mir bleiben noch genau 170 Bytes...

Es gibt 3 verschiedene Musikstücke fürs Intro und Extro, für das Spiel selber und für die Zwischenlevel. Man spielt in mehreren Phasen: 1. Der Autoscrol 2. Der Scrol durch aktiven Joystickeinsatz mit anderen Items 3. Der Endgegner Die Zwischenlevel kommen im Autoscrol.

Das Spiel läßt sich nur mit einem Atari 130 XE spielen. Im PAL-Modus läuft es schön flüssig, NTSC ruckelt leider... das werde ich auch nicht viel besser hinbekommen, da der VBI und die CPU vom Timing komplett ausgelastet sind. Die gesamte Entwicklung des Spiels hat jetzt fast ein Jahr gedauert... ich kann mich noch gut an meine ersten Schritte erinnern, wo ich überlegt habe, wie ich "Hallo Welt" scrollend auf den Bildschirm bringe... Ich hatte große Hilfe von JAC und Sascha auf der Fujiama letztes Jahr mit der Einrichtung meiner Programmierumgebung, danke an alle, die mir hier im Forum immer wieder wichtige Inputs gegeben haben! Mein besonderer Dank gilt natürlich meinem neuen Freund Janko, ohne dessen Beistand in etlichen Fragen wäre das Programm nie so geworden ... danke Janko!!

Ob das Spiel würdig genug für den Wettbewerb ist oder nicht, ist mir gar nicht so wichtig... aber wenn es ein einziger gerne mal spielt und ein wenig Gefallen dran findet, dann bin ich mehr als zufrieden! Gruß Peter

AntwortZitat

Hallo Peter,

irgendwie habe ich Probleme mit dem Spiel. Sehr häufig passiert nichts mit den Objekten wenn ich auf sie schieße. Oder eine Explosion findet irgendwo im normalen Playfield statt wo sich gar kein Objekt befindet. Meine Hardwareconfig: 800XL mit Turbo Freezer / FujiNet

Du hast geschrieben das es nur auf 130XE läuft. Deshalb habe ich es mal im Altirra mit 130 XE Config (OS Rev. 3) probiert: Aber da läuft es auch nicht richtig. Ist ggf. die Version für den Softwarewettbewerb (MAG150H.ATR) defekt?

Schau mal das Video: https://drive.google.com/file/d/1cwzp2OJouqCVg6jLU7cIaA8t--UQ312c/view?usp=sharing

Wenn das Spiel frisch gebootet ist, funktioniert das allererste Mal spielen am besten. Da gehen noch die meisten Objekte kaputt. Aber wenn man dann gestorben ist wird es schon recht schnell "komisch" und reagiert eben nicht mehr richtig.

Altirra Config: Base system PAL 130XE Additional Devices None OS Firmware Atari XL/XE OS ver.3 [29F133F7] Mounted Images Disk: MAG150H.ATR

AntwortZitat

Hallo, vielen Dank für die Rückmeldung! Ich habe gerade die final Version am Mac-Emulator und am Altirra getestet - alles läuft wunderbar! Allerdings - und das ist mir schon auf der Fuji aufgefallen als ich andere beim spielen von BoE beobachtet habe - läuft die Schuss-/Kollisionserkennung nicht bei Dauerfeuer. Das habe ich einfach nicht bedacht und entsprechend abgefangen, da mein Joystick diese Funktion nicht besitzt. Janko und ich haben das Spiel wochenlang getestet und konnten die allermeisten Bugs finden und entfernen - nicht alle allerdings. Manchmal kann man durch die Landschaft schiessen und hin und wieder erkennt er die Kollision nicht, wenn man ein Objekt trifft - es liegt wohl am timing und könnte mit dem Dauerschuss in Zusammenhang stehen. Die Schüsse sind ja gewollt so, daß man immer nur einen Schuss abgeben kann und zwar wechselweise links / rechts. Ich denke wenn man Dauerfeuer drückt, verliert das Programm den Kollisionsstatus... in CavernsOfEris wird es das nicht so geben. Also: Kein Dauerfeuer bitte!! 😉

AntwortZitat

... übrigens... das Spiel ist nicht leicht, aber mit ein wenig Übung kommt man bis zum Endgegner und kann diesen auch besiegen! Ich persönlich bin mehrfach komplett durchgekommen, schaffe es aber auch nicht immer. Am absolut schwierigsten sind die breiten Energiebarrieren, da muss man echt ganz genau das timing hinbekommen. Auch durch das Energielabyrinth muss man erstmal durchkommen - wobei, wenn man den richtigen Weg kennt, ist es gar nicht so schwer 😉

AntwortZitat

Ja, es ist definitiv nicht einfach. Manchmal komme ich nicht mal um die ersten Ecken, oder lande in der Mauer. Versterbe IN der Mauer, also nicht an der Mauer 😁 . Ohne Dauerfeuer. Gespielt am MacBookPro/Intel mit Atari 800 MacX Gruß Wolfgang

AntwortZitat

Tatsächlich! Wenn man nur Einzelschüsse absetzt ohne den Feuerknopf gedrückt zu halten geht es viel besser. ok!

AntwortZitat